Babel - Plugins
In all of the previous articles in our series on Babel, we’ve seen how to convert JavaScript from ES6 to ES5. To do this we made sure the presets were set to 2015. This raises the question, what are these presets exactly, and where do they come from? To understand this, we need to talk about plugins. So let’s forget about presets for a minute and pretend they don’t exist—that we live in a world of plugins alone.
Starting with version 6, Babel works in a modular fashion, meaning one can control precisely what gets converted and how. For example, if I want the compiler to convert let, or maybe the ES6 templating array to something older, I need to state this explicitly. In keeping with Babel methodology, I should download a specific plugin for templating, or for let, and list them specifically in the .babelrc configuration file.
Let’s assume we have the following code:
let myData = {
name: 'Moshe',
debt: '200'
}
let content = `Hi ${myData.name}, You owe me ${myData.debt} USD.`;
document.getElementById('container').textContent = content;
If we want to convert the templating, we’ll have to download the plugin template literals transform using the following:
npm install babel-plugin-transform-es2015-template-literals
Our .babelrc file will show:
{
"plugins": ["transform-es2015-template-literals"]
}
When we run Babel using the console or command prompt (remember how?)
./node_modules/.bin/babel src -d lib -w
the compiled file will look like this:
let myData = {
name: 'Moshe',
debt: '200'
};
let content = 'Hi ' + myData.name + ', You owe me ' + myData.debt + ' USD.';
document.getElementById('container').textContent = content;
There are two really interesting things here. First, we see that the templating was converted successfully; we have no need for curly braces or reverse quotation marks. Second, let wasn’t converted! But why not? Well, simply because we didn’t use a plugin that converts it. This plugin is called block scoping transform and takes care of converting let or const to something an older system will know how to handle—a good ol’ fashioned var!
So how do we install it? Just like the previous plugin. There are detailed instructions in the Babel documentation that contain all of the plugins. But in short:
npm install babel-plugin-transform-es2015-block-scoping
And let us not forget that we must add a seperate line in the .babelrc file, just as we did with the previous plugin:
{
"plugins": [
"transform-es2015-template-literals",
"transform-es2015-block-scoping"
]
}
Let’s quickly run Babel again and see how the compiled file converts let and of course the templating as well:
var myData = {
name: 'Moshe',
debt: '200'
};
var content = 'Hi ' + myData.name + ', You owe me ' + myData.debt + ' USD.';
document.getElementById('container').textContent = content;
Now it looks exactly as we want.
So what’s the problem with plugins? While they do allow us a great deal of customization—which is especially important for when we get to the most recent standards—it can be tiring to list each and every plugin. Indeed, in ES6 (aka ES2015, remember?) there are loads of plugins and changes—and all this before we even get to the polyfils! This is exactly why we have presets!
With presets, what we’re talking about is a collection of plugins. So instead of making a list of 20 some plugins that cover ES2015, we can simply say, “bring me all the plugins that convert ES6 to ES5.” How do we do this? We just install the 2015 preset using:
npm install --save-dev babel-preset-es2015
Then we add the following setting to Babel:
{
"presets": ["es2015"]
}
By doing so, there’s no need to individually add each plugin for ES2015. When we use the preset, it’s like listing all of the following plugins:
check-es2015-constants
transform-es2015-arrow-functions
transform-es2015-block-scoped-functions
transform-es2015-block-scoping
transform-es2015-classes
transform-es2015-computed-properties
transform-es2015-destructuring
transform-es2015-duplicate-keys
transform-es2015-for-of
transform-es2015-function-name
transform-es2015-literals
transform-es2015-modules-commonjs
transform-es2015-object-super
transform-es2015-parameters
transform-es2015-shorthand-properties
transform-es2015-spread
transform-es2015-sticky-regex
transform-es2015-template-literals
transform-es2015-typeof-symbol
transform-es2015-unicode-regex
transform-regenerator
At this point you should have a clear understanding of preset2015. There is also preset2016 and preset 2017 of course, and there will be more in the future. All presets along with the plugins they include are listed in Babel’s documentation.
To demonstrate, let’s write a little ES2017. At the time of this writing, one of ES2017’s new modules proposes allowing trailing commas in function parameter lists without it causing problems. Not terribly important if you ask me, but good enough for an example.
In ES2017 it’s totally OK to write something like this:
function myFunc(arg1, arg2<strong>,</strong>) {
console.log(arg1, arg2);
}
myFunc('Hello', 'World'<strong>,</strong>);
Notice the commas at the end. This is something that will cause almost any browser or environment to crash unless it has trailing commas in function syntax. But if we have Babel, there’s no need to worry. We can see in the documentation that there is the syntax-trailing-function-commas plugin, which is part of the preset2017. Install the preset like this:
npm install --save-dev babel-cli babel-preset-es2017
Don’t forget to add the preset2017 along with preset2015 that’s already in the .babelrc file:
{
"presets": ["es2015", "es2017"]
}
Let’s run the whole shebang with our favorite command:
./node_modules/.bin/babel src -d lib -w
Here is the code before compiling—it has both ES2015 and ES2017:
let content = `Hi ${myData.name}, You owe me ${myData.debt} USD.`;
document.getElementById('container').textContent = content;
function myFunc(arg1, arg2,) {
console.log(arg1, arg2);
}
myFunc('Hello', 'World',);
The ES2015 comes into play with the templating and the let, and the ES2017 with the comma at the end of the list of arguments in the function definition, and with the function call. This code will fail in almost all browsers, and definitely in all versions of Node.js. But right after running the compiler, we receive this code:
'use strict';
var content = 'Hi ' + myData.name + ', You owe me ' + myData.debt + ' USD.';
document.getElementById('container').textContent = content;
function myFunc(arg1, arg2) {
console.log(arg1, arg2);
}
myFunc('Hello', 'World');
And this code, ladies and gentlemen, can run in versions of Node.js that Kaiser Wilhelm would be embarrassed to use, or in Internet Explorer versions from back when its top competitor was Netscape.
There are more presets—for example latest which includes ES2015, ES2016, and ES2017. There are also ‘unofficial’ Babel presets that various individuals have made. At the end of the day, presets are just a collection of plugins, and anyone can write a plugin.
What happens if we use a preset that includes a plugin that we’ve already included separately? In Babel, compilation is not according to the listed order. A plugin converts what it can from the code, and then passes over to the next plugin, and it continues on like that, one at a time. The order in Babel 6.5 goes like this: first come the plugins, from first to last, and then come the presets, from last to first.
Notice that things really start to heat up when we talk about the newest, shiniest features of ECMAScript. No need to wait for the standard to be set in stone. Each newly suggested addition to the standard goes through four stages:
Stage 0 - just an idea
Stage 1 - an actual proposition
Stage 2 - first draft and specifications
Stage 3 - candidate to be entered into the standard
Stage 4 - entry into the standard
When a new standard begins to crystallize, e.g. ES2017, a large part of it is still in stage 0, and other parts are in the other stages. They too have their own presets. If one uses preset stage 0, they’ll already be able to use plugins and changes in the new standard that have yet to reach that later stages. Of course, use these at you own risk.
There are other topics in Babel—how to use it with grunt, or gulp, or webpack—but they’re topics better suited to a different series.
About the author: Ran Bar-Zik is an experienced web developer whose personal blog, Internet Israel, features articles and guides on Node.js, MongoDB, Git, SASS, jQuery, HTML 5, MySQL, and more. Translation of the original article by Aaron Raizen.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment