How to use babel-preset-env with Jest
Asked Answered
A

3

5

We are in the midst of updating our API, and Henry Zhu from Babel alerted me to this preset called babel-preset-env to replace need for babel-preset-es2015 and babel-preset-es2018.

Now, I am encountering difficulty understanding the simplest way to handle everything.

  • Our API uses node v8.x and async/await, native promises
  • I want spread operator
  • I want pipeline operator
  • I want import/export syntax
  • I want to support Jest
  • I like how babel-node transpiles the API into memory

This will be easier if I just show you the current position of our config:

.babelrc

 {
   "presets": [
     "env",
       {
         "targets": {
           "node": "current"
         }
       },
     "jest"
   ]
 }

package.json

 {
   "scripts": {
     "test": "node --harmony-async-await node_modules/jest/bin/jest.js",
     "start:local": "NODE_ENV=localhost npm run babel-node -- warpcore/server.js",
     "start": "npm run babel-node -- warpcore/server.js",
     "babel-node": "babel-node --presets=es2015,stage-2"
   },
   "dependencies": {
     "babel-polyfill": "^6.23.0"
   },
   "devDependencies": {
     "babel-cli": "^6.24.1",
     "babel-core": "^6.25.0",
     "babel-eslint": "^7.2.3",
     "babel-jest": "^20.0.3",
     "babel-preset-env": "^1.6.0",
     "babel-preset-es2015": "^6.24.1",
     "babel-preset-es2018": "^1.0.0",
     "babel-preset-stage-2": "^6.24.1",
     "jest": "^20.0.4"
   },
   "jest": {
     "testURL": "http://localhost:8080",
     "testEnvironment": "node"
   }
 }

I am uncertain how these things need to be organized to best achieve my bullet list above.

What changes should I make?

  • I think the babel-node script needs to change
  • I suspect I can remove some of these packages
  • I suspect the .babelrc file isn't optimal
Arletha answered 22/7, 2017 at 22:9 Comment(0)
A
5

I think I got it working. Here is the solution:

.babelrc

The one posted in the question has a syntax error because the env preset needs to be wrapped in brackets[] (from: http://babeljs.io/docs/plugins/preset-env/)

Correct:

 {
   "presets": [
     ["env",
       {
         "targets": {
           "node": "current"
         }
       }],
     "jest"
   ]
 }

package.json

The one posted in the question has a few things that can be removed:

  {
     "scripts": {
       "test": "jest --verbose",
       "start:local": "cross-env NODE_ENV=localhost babel-node -- app.js",
       "babel-node": "babel-node --presets=env"
    },
    "dependencies": {
      "babel-cli": "^6.24.1",
      "babel-preset-env": "^1.6.0"
    },
    "devDependencies": {
      "babel-eslint": "^7.2.3",
      "babel-jest": "^20.0.3",
      "jest": "^20.0.4"
    },
    "jest": {
      "testURL": "http://localhost:8080",
      "testEnvironment": "node"
    }
  }

Much cleaner in my opinion. You can modulate the presets from the .babelrc file if you want to explicitly include or exclude any, or specify which browsers to support.

Arletha answered 23/7, 2017 at 18:19 Comment(2)
Update: I've been using exactly what is shown in the accepted answer for a couple months now, and it works well.Arletha
How do you do the implementation for production? babeljs.io/docs/en/babel-cli#not-meant-for-production-use Not meant for production use You should not be using babel-node in production. It is unnecessarily heavy, with high memory usage due to the cache being stored in memory. You will also always experience a startup performance penalty as the entire app needs to be compiled on the fly. Check out the example Node.js server with Babel for an idea of how to use Babel in a production deployment.Kentigerma
A
8

If you want to use babel-preset-env as a replacement for babel-preset-es2015 (which is deprecated) with Jest, then you have to make sure that the "modules" property in your "env" configuration is set to "commonjs".

Here is an exemplary configuration:

.babelrc

{     
  "env": {
    "test": {
      "plugins": [
        "transform-class-properties",
        "transform-object-rest-spread"
      ],
      "presets": [
        "jest",
        "react",
        [
          "env",
          {
            "debug": false,
            "modules": "commonjs",
            "targets": {
              "node": "current"
            },
            "useBuiltIns": true
          }
        ]
      ]
    }
  }
}

You can see in env.test, that the preset env (which is the "babel-preset-env" configuration) has "modules" set to "commonjs". That's important, otherwise you will get "SyntaxError: Unexpected token import".

For completeness, here is a simple test:

ExampleButton.test.jsx

import ExampleButton from './ExampleButton';
import React from 'react';
import renderer from 'react-test-renderer';

test('Example Test', () => {
  const component = renderer.create(<ExampleButton />);
  const json = component.toJSON();
  expect(json.type).toBe('button');
});

ExampleButton.jsx

import React from 'react';

class ExampleButton extends React.Component {
  render() {
    return (
      <button onClick={this.props.onClick}>
        {this.props.text}
      </button>
    )
  }
}

export default ExampleButton;

For my Babel setup, I have used the following dependencies:

"babel-core": "6.26.0",
"babel-jest": "21.2.0",
"babel-plugin-transform-class-properties": "6.24.1",
"babel-plugin-transform-object-rest-spread": "6.26.0",
"babel-preset-env": "1.6.1",
"babel-preset-react": "6.24.1",
"jest": "21.2.1",
"react-test-renderer": "16.1.1",
Anther answered 27/11, 2017 at 16:39 Comment(2)
I found this out the hard way when moving from Babel 6 to 7 where Babel 6 had modules: 'commonjs' by default whereas Babel 7's preset-env doesn't. But why does jest need commonjs modules? I never really understood that part, no matter how much i read about the differences between commonjs, amd, umd etc. Is there an easy explanation for why jest absolutely needs commonjs?Blowgun
@Blowgun Because Jest hooks into the require function to handle mocking dependencies; it can't do the same with import statements. Additionally, imports are not yet supported in non-experimental node environments, hence the syntax error.Subdiaconate
A
5

I think I got it working. Here is the solution:

.babelrc

The one posted in the question has a syntax error because the env preset needs to be wrapped in brackets[] (from: http://babeljs.io/docs/plugins/preset-env/)

Correct:

 {
   "presets": [
     ["env",
       {
         "targets": {
           "node": "current"
         }
       }],
     "jest"
   ]
 }

package.json

The one posted in the question has a few things that can be removed:

  {
     "scripts": {
       "test": "jest --verbose",
       "start:local": "cross-env NODE_ENV=localhost babel-node -- app.js",
       "babel-node": "babel-node --presets=env"
    },
    "dependencies": {
      "babel-cli": "^6.24.1",
      "babel-preset-env": "^1.6.0"
    },
    "devDependencies": {
      "babel-eslint": "^7.2.3",
      "babel-jest": "^20.0.3",
      "jest": "^20.0.4"
    },
    "jest": {
      "testURL": "http://localhost:8080",
      "testEnvironment": "node"
    }
  }

Much cleaner in my opinion. You can modulate the presets from the .babelrc file if you want to explicitly include or exclude any, or specify which browsers to support.

Arletha answered 23/7, 2017 at 18:19 Comment(2)
Update: I've been using exactly what is shown in the accepted answer for a couple months now, and it works well.Arletha
How do you do the implementation for production? babeljs.io/docs/en/babel-cli#not-meant-for-production-use Not meant for production use You should not be using babel-node in production. It is unnecessarily heavy, with high memory usage due to the cache being stored in memory. You will also always experience a startup performance penalty as the entire app needs to be compiled on the fly. Check out the example Node.js server with Babel for an idea of how to use Babel in a production deployment.Kentigerma
M
0

This is the solution I found:

{
  "presets": ["@babel/env", "@babel/react"]
}
Merriweather answered 3/10, 2019 at 8:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.