Babelify your JavaScript code

JavaScript is the only language that runs in the browser, but even then not all browser vendors implement the latest feature of JavaScript, or they did implement it, but then again it’s only for the latest version of the browser. So what if we, as developers, want to implement a feature of JavaScript that’s sadly not yet available in the browser? What if we also want to support older browser versions and not only the latest one? This is the problem that has been solved by Babel, the web developer tool for transpiling JavaScript code into older version of it.

In a very generic non-jargon way, it means Babel takes a modern JavaScript code and turn it into an older version that’s understood by browsers.

For example, let’s take arrow function, which is released in ES6

[1, 2, 3].map((n) => n + 1);

This code will work fine in recent versions of Chrome (61+ if I’m not mistaken) but not in Internet Explorer. So to make the code work in IE, we have to transpile the code into ES5 version.

[1, 2, 3].map(function(n) {
  return n + 1;
});

This is what Babel does in a nutshell. It takes modern JavaScript and rewrite it into a prior version that’s compatible with older browsers. It also allows us to use experimental or very recent release of JavaScript version into our code.

Babel Setup

To install Babel, go into your project root directory and hit the command line:

npm install --save-dev @babel/core @babel/cli
npm install --save @babel/polyfill
npm install --save-dev @babel/preset-env

Then create a new config file named babel.config.js with this content:

const presets = [
  [
    "@babel/env",
    {
      targets: {
        edge: "17",
        firefox: "60",
        chrome: "67",
        safari: "11.1",
      },
      useBuiltIns: "usage",
    },
  ],
];

module.exports = { presets };

Note that the browsers list above is just an arbitrary example. You will have to adapt it for the browsers you want to support. Now let’s run Babel to transpile all the code from src/ directory into lib/:

npx babel src --out-dir lib

To run babel on a single file you can use:

npx babel script.js

Explaining the installed packages

All npm packages of Babel are scoped under @babel to allow a structured and specific babel packages order. The packages we have installed above are the minimum we needed to run Babel. @babel/core is the main functionality of Babel that’s responsible for transpiling your code. It needed some kind of interface for access. @babel/cli allows you to access Babel from the Terminal, hence we can run the npx babel command. We can add arguments like the --out-dir option above. You can view the rest of the options accepted by the cli tool by running it with --help. But the most important options for us to learn right now are --plugins and --presets

Plugins

These are small JavaScript programs responsible for carrying out the transpiling tasks. For example, to transform arrow functions into a regular function, we can use @babel/plugin-transform-arrow-functions official plugin.

npm install --save-dev @babel/plugin-transform-arrow-functions

Then add it to our babel.config.js

const presets = [
  [
    "@babel/env",
    {
      targets: {
        edge: "17",
        firefox: "60",
        chrome: "67",
        safari: "11.1",
      },
      useBuiltIns: "usage", // for using babel-polyfill
    },
  ],
];

const plugins = ["@babel/transform-arrow-functions"]

module.exports = { presets, plugins };

Now we are transforming arrow functions into regular functions.

Presets

But then again, specifying each and every one of the plugins would be exhausting, isn’t it? That’s why Babel has presets, which is a pre-determined set of plugins.

Just like with plugins, you can create your own presets to share any combination of plugins you need. For our use case here, there’s an excellent presets named env which support all modern JavaScript (ES2015, ES2016, etc.). You can use it from the terminal.

npm install --save-dev @babel/preset-env
npx babel src --out-dir lib --presets=@babel/env

Or use the config file like how we have done above.

Preset targets option

The target options of presets will allow you to target specific version of browsers to support, but it can also be smarter than that.

For example, let’s say we want to support the last 3 versions of every browser, but for Safari let’s support all versions since Safari 8

const presets = [
  [
    "@babel/env",
    {
      targets: {
        "browsers": ["last 3 versions", "safari >= 8"]
      },
      useBuiltIns: "usage",
    },
  ],
];

const plugins = ["plugin-transform-arrow-functions"]

module.exports = { presets, plugins };

Running Babel with webpack

In order to run babel with webpack, we can use the babel-loader from webpack and put our babel configuration into it. So on our webpack.config.js:

entry: [
  'babel-polyfill',
  // your app scripts should be here
],

module: {
  loaders: [
    // Babel loader compiles ES2015 into ES5 for
    // complete cross-browser support
    {
      loader: 'babel-loader',
      test: /\.js$/,
      // only include files present in the `src` subdirectory
      include: [path.resolve(__dirname, "src")],
      // exclude node_modules, equivalent to the above line
      exclude: /node_modules/,
      query: {
        // Use the default ES2015 preset
        // to include all ES2015 features
        presets: ['@babel/env'],
        plugin: ['@babel/plugin-transform-arrow-functions']
      }
    }
  ]
}

By keeping the presets and plugins information inside the webpack.config.js file, we can discard babel config file from our project directory.

Take your skills to the next level ⚡️

I'm sending out an occasional email with the latest tutorials on programming, web development, and statistics. Drop your email in the box below and I'll send new stuff straight into your inbox!

No spam. Unsubscribe anytime.