Babel preset to be used at MOXY.
$ npm install babel-preset-moxy @babel/core --save-dev
If you are using Jest for testing, you also need to install
$ npm install babel-jest --save-dev
add-module-exportsto get around babel#2212
Do I need to transpile?
There has been discussion in the community about libraries not being compiled, leaving all compilation efforts to top-level projects consuming them. This makes sense, since developers know what platforms their top-level project target and are able to compile their dependencies accordingly. Furthermore, library maintainers are constantly having to update their compilation options as new features are accepted into different stages of the specification, which creates significant and unnecessary overhead.
1. Choose a preset-type
There're two preset types available for you to use:
- For libraries: use the
libtype in case you are developing a library to be consumed by others
- For end-projects: use the
end-projecttype in case you developing a top-level project, such as an Web Application, a Node.js API or CLI
2. Setup babel within your project
The way Babel is configured depends on the the tooling you are using. Below, there are instructions for common scenarios:
If you don't use a bundler within your project, this is the setup guide you should follow
.babelrcat the root of your project, replacing
<preset-type>with the preset type you chose:
...or with options:
@babel/clias a dev dependency because we will need it for the build script:$ npm install @babel/cli --save-dev
Set up your
package.jsonlike this:"main": "lib/index.js","module": "es/index.js","files":,"scripts":
Note that the build process above will produce both CommonJS and ES builds. If you just want to produce a single build, the
package.jsonmay be simplified. For example, to produce a single CommonJS build:"main": "lib/index.js","files":,"scripts":
es/folder to the gitignore file so that those output folders are never committed.
src/index.jsand happy coding!
Webpack based project
babel-loader and MOXY's preset. Here's an example for a website project using React:
test: /\.js$/use:loader: requireoptions:cacheDirectory: true // Improve performancepresets:requiretargets: 'browsers'react: truemodules: false
It's important that you do not exclude the
node_modules folder so that everything goes through the
@babel/preset-env, ensuring that all the produced code was transpiled according to the targets.
3. Tweak the options
Below, you may find a list containing all options you may tweak:
|react||Adds support for React||boolean||false||✅||✅|
|lodash||Transform to cherry-pick Lodash modules||boolean/Object||true||✅||✅|
|modules||Transform ES6 module syntax to another module type||string/boolean||Based on
|dynamicImport||Adds support for
|loose||Enable "loose" transformations for any plugins that allow them||boolean||true||❌||✅|
|targets||The output targets, see bellow for a more detailed explanation||Array/Object||['browsers', 'node']||❌||✅|
|env||The environment (
|namedDefaultExport||Use add-module-exports plugin to get around babel/babel#2212||boolean||true if modules is
Specify which modules will have the cherry-pick transformation applied.
lodash/fp are always added for you, regardless of having this option defined or not.
For instance, to have smaller bundles when using recompose:
The targets option has a very important role. By default, its value is
['browsers', 'node'] which means that the compiled code will work in both the Browser and in Node.js.
browsers is specified, the compiled code will work on browsers that are supported by Google's browser support policy. When
node is specified, the compiled code will work on the last LTS or higher (currently
If your project has different requirements in terms of browser or node support, you may specify the targets yourself as an object.
Dynamic imports support are enabled by default but are dependent on the
modules option. More specifically, the
dynamic-import-node when the
modules option is set to
modules types, such as
amd, you must find and include a plugin yourself. Also, you may disable the
dynamicImport option by setting it to
false in case you want to disable the feature completely or if you want to choose another plugin.
env's default value respects
process.env.NODE_ENV and falls back to
production if none are set. When env is
production, some plugins that perform code optimization will be enabled.
modules default value is
process.env.BABEL_ENV is set to
4. Be aware of the caveats
No, seriously. Read the Caveats section as it contains crucial information and might require you to do a few more steps.
Shipping polyfills in libraries is, in general, a bad practice because it increases the overall file size of your top-level project due to duplication.
transform-runtime plugin attempts to solve the polyfills and duplication by transforming
Promise and other features to their
core-js counter-parts. Though, this doesn't play well with
preset-env because it inlines everything, including features that are already supported by our targets. Additionally, if different versions of the runtime are installed, duplication still happens.
In top-level projects
import 'babel-polyfill'; at the top of your entry file. That statement will be replaced with the necessary polyfills based on the targets you want to support.
// in:;// out:;;// ...
The support for dynamic imports is enabled by default, please read more on the
The caveat is that
preset-env is unaware that using
import() with Webpack relies on Promise internally. Environments which do not have builtin support for Promise, like Internet Explorer, will require both the promise and iterator polyfills be added manually. Having said that, tweak your top-level project's Webpack config like so:
entry:'core-js/modules/es6.promise''core-js/modules/es6.array.iterator'// Path to your entry file;
You must use a minifier that understands ES6+ syntax because the transpiled code might contain ES6+ code. As an example, UglifyJS v2 only understands ES5 syntax but UglifyJS v3 does support ES6+.
$ npm test$ npm test -- --watch # during development