babel-preset-moxy
Babel preset to be used at MOXY.
Installation
$ npm install babel-preset-moxy --save-dev
You might need to also install babel-cli as a dev dependency.
Please read the Caveats section because it contains important notes that you should be aware of.
Motivation
If you are developing a project that uses new ECMAScript language features and must work on targets that do not yet support them, you have to transpile your code. This preset provides a shareable Babel config as a preset that should be used across those projects at MOXY.
Please note that there are few reasons to use Babel when you are developing a library that only targets Node.js because the latest LTS and current version support 99% of ES8.
Usage
Create .babelrc
at the root of your project:
{
"presets": ["moxy"]
}
...or with options:
{
"presets": [["moxy", { "react": true }]]
}
Set up your package.json
like this:
"main": "lib/index.js",
"module": "es/index.js",
"files": [
"lib",
"es"
],
"scripts": {
"build:commonjs": "BABEL_ENV=commonjs babel src -d lib",
"build:es": "BABEL_ENV=es babel src -d es",
"build": "npm run build:commonjs && npm run build:es"
}
And finally create src/index.js
and start coding!
Available options:
Name | Description | Type | Default |
---|
env | The environment (development , production or test ) | string | Based on process.env.NODE_ENV |
targets | The output targets, see bellow for a more detailed explanation | Array/Object | ['browsers', 'node'] |
react | Adds support for React | boolean | false |
modules | Transform ES6 module syntax to another module type | string/boolean | Based on process.env.BABEL_ENV |
namedDefaultExport | Use add-module-exports plugin to get around babel/babel#2212 | boolean | true if modules is commonjs |
lodash | Transform to cherry-pick Lodash modules | boolean/Object | true |
The 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.
The modules
default value is commonjs
unless process.env.BABEL_ENV
is set to es
.
targets
option
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.
When 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 v8.9
).
If you are developing a library or application that has different requirements in terms of browser or node support, you may specify the targets yourself as an object.
lodash
option
Specify which modules will have the cherry-pick transformation applied.
Note that lodash-es
, lodash-compat
and lodash/fp
are always added for you, regardless of having this option defined or not.
For instance, to have smaller bundles when using recompose:
{
"presets": [
["moxy", {
"lodash": { "id": ["recompose"] }
}]
]
}
Caveats
Polyfills
For libraries
Shipping polyfills in libraries is, in general, a bad practice because it increases the overall file size of your app due to duplication.
The transform-runtime plugin attempts to solve the polyfills and duplication by transforming Object.assign
, 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.
For this reason, you, as an author, should state in the README of your library that you expect the environment to be polyfilled with core-js, babel-polyfill, polyfill.io or similar. If your library uses async await
, you should also state that you depend on having regenerator-runtime installed globally.
For applications
Simply include import 'babel-polyfill';
or import 'core-js';
at the top of your main app file.
Those statements will be replaced with the necessary polyfills based on node/browser support.
import 'babel-polyfill';
import 'core-js/modules/es6.object.assign';
import 'core-js/modules/es6.promise';
Note that if you are only targeting environments that already support async await
natively, such as Nodejs >= v8, the regenerator-runtime
won't be installed automatically. This is fine, except if your app uses dependencies that rely on the regeneratorRuntime
global.
To get around this, you must have regenerator-runtime/runtime
required at the top of your main app file. Alternatively, if you use Webpack, you may use the ProvidePlugin as follows:
{
plugins: [
new ProvidePlugin({
regeneratorRuntime: require.resolve('regenerator-runtime'),
}),
]
}
Dynamic imports
This preset does not provide support for dynamic imports.
If you are only targeting Browsers and you are bundling your code with a bundler that recognizes dynamic import statements (e.g.: Webpack), you may want to activate syntax-dynamic-import.
If you are only targeting Node.js, you may want to use dynamic-import-node but beware that this won't work for browsers.
Minifying
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+.
Tests
$ npm test
$ npm test -- --watch
during development
License
MIT License