Configuring Babel 6
Update: This series of blog post has been turned into the book “Setting up ES6” (which is free to read online).
Babel 6 is much more configurable than Babel 5, but also more difficult to configure. This blog post gives tips.
Follow-up blog posts:
- [2015-12-11] Babel 6: configuring ES6 standard library and helpers
- [2015-12-12] Babel 6: loose mode
- [2015-12-13] Babel and CommonJS modules
Installing Babel 6
The following are a few important npm packages. All Babel packages reside in a single repository on GitHub. Browsing their source code and their package.json
files is instructive.
babel-core
: the core compilation machinery and plugin infrastructure for Babel. You will rarely need to install this package, because other packages such asbabel-cli
have it as a dependency, meaning that it will be automatically installed when they are installed.babel-cli
: a command line interface toBabel
. It includes the following commands:babel-doctor
detects common problems with your Babel installation.babel
transpiles files or stdin via Babel.babel-node
a version of the Node.js executablenode
that transpiles everything via Babel.babel-external-helpers
prints all of Babel’s helper functions (such asinherits
for subclassing) to the console.
babel-register
: lets you switch on Babel transpilation from within Node.js. After you do, all modules you require (minus code you want to ignore, e.g. packages installed via npm) are automatically transpiled.
Configuration data
Babel is often about compiling an input file, e.g. in the following two scenarios:
Compiling a file via the command line tool
babel
:
babel input-es6.js --out-file output-es5.jsRunning a Node.js script written in ES6:
babel-node input-es6.js
The configuration data is an object of JSON data that is assembled from various sources (which are described later). Two configuration options have much influence on how the output is produced: plugins and presets.
Plugins
Roughly, plugins are functions that are applied to the input during compilation. Two important categories of plugins are:
- Syntax plugins enable Babel to parse syntactic entities beyond the built-in base syntax. They help with constructing an abstract syntax tree. Examples are:
- Transform plugins modify the abstract syntax tree. Examples are:
- transform-async-to-generator
- transform-react-jsx
- transform-es2015-arrow-functions
- transform-es2015-classes
If you want to compile something that isn’t part of the base syntax, you need both a syntax plugin and a corresponding transform plugin. However, each transform plugin that depends on a syntax plugin automatically activates that plugin.
Plugins are installed via npm. Their package names are their names plus the prefix babel-plugin-
:
- Plugin
syntax-jsx
:npm install babel-plugin-syntax-jsx
- Plugin
transform-react-jsx
:npm install babel-plugin-transform-react-jsx
Presets
In order to configure Babel’s output to your liking, you need to specify what plugins it should use. You can specify:
- Individual plugins
- Presets, sets of plugins that support various compilation scenarios.
The following are useful presets:
- es2015: compiles ES6 (as described by the ECMAScript spec) to ES5
- stage-3: compiles stage 3 ECMAScript proposals to ES5
- react: compiles JSX to JavaScript and removes Flow type annotations
- es2015-node5: Contains just those plugins that are needed to upgrade Node.js 5 to full ES6. Therefore, a lot less is transpiled than with the
es2015
preset. Especially generators not being transpiled helps with debugging.
Presets are installed via npm. Their package names are their names plus the prefix babel-preset-
. For example, this is how to install the preset es2015
:
npm install babel-preset-es2015
Sources of configuration data
The configuration data is always located relative to the input file:
- When ascending through parent directories, whichever of the following two files is found first is used. If they are both in the same directory then
.babelrc
is used..babelrc
: The file’s contents are interpreted as JSON and used as Babel options.package.json
: Propertybabel
of the file’s JSON content is used as Babel options. This file only counts if it has the propertybabel
.
.babelignore
: The “first” file in the parent directories is used. Its lines are turned into an Array and interpreted as the optionignore
.
Two properties in configuration data specify additional configuration data:
- Property
env
of maps the names of environments ('development'
,'production'
, etc.) to objects with more configuration data. Ifenv
exists, the object corresponding to the current environment is merged with the configuration data that has already been assembled. Consult the Babel documentation for more information on environments. - Property
extends
contains a path pointing to a file with more configuration data.
babel-node
If you are using babel-node
, you can also specify the following options (and a few others) via the command line:
--presets
--plugins
--ignore
: by default, any file that has the segment'node_modules'
in its path is not transpiled.
The following command runs my-script.js
via babel-node
, with the presets es2015-node5
and react
, and the plugin transform-async-to-generator
enabled.
babel-node \
--presets es2015-node5,react \
--plugins transform-async-to-generator \
my-script.js
On Unix, if a file is executable and contains the following first line then you can directly execute it, via babel-node:
#!/usr/bin/env babel-node
You could specify presets etc. as options at the end of this line, but doing so via package.json
seems cleaner. This is a minimal package.json
for a project with an executable:
{
"name": "tools",
"dependencies": {
"babel-cli": "^6.1.2",
"babel-preset-es2015-node5": "^1.1.0",
},
"bin": {
"foo" : "./bin/foo.js"
},
"scripts": {
"foo": "./bin/foo.js"
},
"babel": {
"presets": [
"es2015-node5"
]
}
}
There are several ways of running foo.js
:
You can execute
foo.js
directly (if it is executable and starts with the right prolog):
cd tools/
./bin/foo.jsYou can execute
foo.js
vianpm run
(as configured inscripts
):
cd tools/
npm run foo arg1 arg2If you install package
tools
globally, you get a command line commandfoo
(as specified viabin
).If you install package
tools
locally, as a dependency of another package, you can executefoo
via thescripts
of that package, as if it was a globally installed command. That’s because npm adds thebin
entries of all dependencies to the shell path before executingscripts
(alas, not thebin
entries in the samepackage.json
).
webpack
The following is an excerpt of webpack.config.js
in the repo react-starter-project.
var path = require('path');
···
module.exports = {
···
module: {
loaders: [
{
loader: 'babel-loader',
test: path.resolve(__dirname, 'js'),
query: {
presets: ['es2015'],
},
}
]
},
···
};
As you can see, babel-loader supports the property query
for specifying Babel options.
More information
The Babel docs are excellent. For example, this page explains the Babel options. The bar at the top gets you to other pages.
Additionally, the following files in Babel’s source code are helpful for figuring out how it handles options:
option-manager.js
contains the algorithm for finding and merging Babel options._babel-node.js
contains the parameter handling code for babel-node.babel-register for Node.js is hosted here.
Comments
Post a Comment