babel-preset-env
: a preset that configures Babel for youbabel-preset-env
is a new preset that lets you specify an environment and automatically enables the necessary plugins.
At the moment, several presets let you determine what features Babel should support:
babel-preset-es2015
, babel-preset-es2016
, etc.: incrementally support various versions of ECMAScript. es2015
transpiles what’s new in ES6 to ES5, es2016
transpiles what’s new in ES2016 to ES6, etc.babel-preset-latest
: supports all features that are either part of an ECMAScript version or at stage 4 (which basically means the same thing).The problem with these presets is that they often do too much. For example, most modern browsers support ES6 generators. Yet, if you use babel-preset-es2015
, generator functions will always be transpiled to complex ES5 code.
babel-preset-env
works like babel-preset-latest
, but it lets you specify an environment and only transpiles features that are missing in that environment.
Note that that means that you need to install and enable plugins and/or presets for experimental features (that are not part of babel-preset-latest
), yourself.
On the plus side, you don’t need es20xx
presets, anymore.
For browsers you have the option to specify either:
Browsers via browserslist query syntax. For example:
Support the last two versions of browsers and IE 7+.
"babel": {
"presets": [
[
"env",
{
"targets": {
"browsers": ["last 2 versions", "ie >= 7"]
}
}
]
]
},
Support browsers that have more than 5% market share.
"targets": {
"browsers": "> 5%"
}
Fixed versions of browsers:
"targets": {
"chrome": 56
}
If you compile your code for Node.js on the fly via Babel, babel-preset-env
is especially useful, because it reacts to the currently running version of Node.js if you set the target "node"
to "current"
:
"babel": {
"presets": [
[
"env",
{
"targets": {
"node": "current"
}
}
]
]
},
If you want to see this target in action, take a look at my GitHub repository async-iter-demo
.
babel-preset-env
This section gives a brief overview of additional options for babel-preset-env
. For details, consult the preset’s readme file.
modules
(string, default: "commonjs"
) This option lets you configure to which module format ES6 modules are transpiled:
"amd"
, "commonjs"
, "systemjs"
, "umd"
false
include
, exclude
(Array of strings, default: []
) include
always enables certain plugins (e.g. to override a faulty native feature). It has the same effect as enabling plugins separately.exclude
prevents certain plugins from being enabled.useBuiltIns
(boolean, default: false
) Babel comes with a polyfill for new functionality in the standard library. babel-preset-env
can optionally import only those parts of the polyfill that are needed on the specified platform(s).
There are two ways of using the polyfill:
core-js
polyfills ES5, ES6+ as needed.
npm install core-js --save
import "core-js";
babel-polyfill
polyfills core-js
and the regenerator runtime (to emulate generators on ES5).
npm install babel-polyfill --save
import "babel-polyfill";
Either of the two import statements is transpiled to an environment-specific sequence of more fine-grained imports. For example:
import "core-js/modules/es7.string.pad-start";
import "core-js/modules/es7.string.pad-end";
import "core-js/modules/web.timers";
import "core-js/modules/web.immediate";
import "core-js/modules/web.dom.iterable";
Things to note:
useBuiltIns
means that less code is downloaded to the browser (bundle sizes become smaller). However, it does not save RAM, because the polyfill only installs what is missing.For more on polyfilling the standard library, consult chapter “Babel: configuring standard library and helpers” in “Setting up ES6”.
debug
(boolean, default: false
) Logs the following information via console.log()
:
Check the next section for sample output.
The following example is taken from the preset’s readme file:
{
"presets": [
[ "env", {
"targets": {
"safari": 10
},
"modules": false,
"useBuiltIns": true,
"debug": true
}]
]
}
Modules are not transpiled. We can, e.g., rely on webpack to handle imports and exports for us.
The debug
output is as follows:
Using targets:
{
"safari": 10
}
Modules transform: false
Using plugins:
transform-exponentiation-operator {}
transform-async-to-generator {}
Using polyfills:
es7.object.values {}
es7.object.entries {}
es7.object.get-own-property-descriptors {}
web.timers {}
web.immediate {}
web.dom.iterable {}
babel-preset-env
get its information? plugin-features.js
."> 1%"
and "last 2 versions"
.Plans for the future include giving plugins the ability to examine what is possible in the current “environment”. That would have two benefits:
Some plugins (such as the one for the object spread operator) currently have options telling them whether to use native functionality or polyfills. If they were aware of their “environment”, the plugins wouldn’t need those options.
Babel-based minifiers can determine whether it’s OK to output, e.g., arrow functions.
Presets based on ECMAScript versions (es2015
etc.) are mostly made obsolete by env
. The Babel team is considering eliminating them in future Babel releases (e.g. via a deprecation process).
Presets based on stages of the TC39 process (stage-3
etc.) are also candidates for removal, as things related to stages are in constant flux. You can’t really rely on anything in this space, because the stage of a proposal can change within 2 months. Therefore, directly referring to plugins of experimental features is the better approach.
babel-preset-env