Using Babel in 2017

July 03, 2017

The JavaScript environment has been changing rapidly in recent years. As new frameworks and technologies draw more developers to JavaScript, those professionals find ways to improve the language. These rapid changes are difficult for browsers and standards to keep up with. This adaption time leads developers to implement language features that can compile back to the core language without having to wait for standards to catch up.

The most widely supported version of JavaScript is the ECMAScript 5 (ES5) standard. This is still the major version of JavaScript that developers must target thanks to a sizable Internet Explorer 11 market share. To add a new language feature, a developer will write new functionality that can be compiled back to ES5-compatible code.

There are a wide variety of standards that have sprung up around JavaScript. There’s a compatibility table that I like to use to track feature adoption of browsers and toolsets.

For example, a developer may want to have a new type of math operator in the language that adds then multiplies a number:

var k = 2;
return k +* 3; // 15 = ((2 + 3) * 3)

To accomplish this the developer will take their custom source code, replace references to the new operator, and generate ES5 source code. The generated code will run correctly in browsers and they’ll be able to use this new feature in their program. This process is called transpilation or source-to-source compilation.

Another option: add functionality to an existing object. For instance, adding custom functionality to the Array object. This can be done by running a script ahead of the rest of the code that relies on that new functionality. This is called a polyfill.

These two strategies allow developers to access modern functionality without sacrificing compatibility. It’s a compelling offer and comes with the bonus that developers can learn the new version of a language before it even gets released.

Why Babel?

Babel is the industry standard tool for transpilation and polyfilling. It works with a wide variety of technologies and frameworks offering transpilation back to an established standard. After transpilation, Babel also provides source maps which allow you too debug through your original code rather than the compiled code.

Keep in mind that adoption means that you are now really using a Babel-JavaScript standard. There are a variety of decisions that Babel makes when implementing their solution that may differ from the ECMAScript standard. This is especially true when implementing experimental functionality in ES7 and beyond. My suggestion for battling this issue is to add testing. Testing is cheap

Common Mistake: When I first tried out Babel I figured that transpiling all of my code would get me all the way to ES6. This isn’t true. In order to fully get there you’ll also need to use the babel-polyfill tool to add the polyfill scripts.

Babel is the best tool for the job for those using JavaScript. I think that there are a lot of advantages to using TypeScript these days, but sometimes you can’t beat vanilla JavaScript.

Setting up Babel with NPM

Now let’s see what it looks like to work with Babel. I’ll describe how to setup basic NPM scripts to be run from the package.json file. I like using NPM because it’s a barebones solution that can work with almost any build system. Also using the raw commands helps me understand exactly what’s happening rather than just relying on the build system.

First up, lets create a new folder and get some babel things installed:

npm init -y
npm i -D babel-cli babel-preset-es2015 babel-polyfill

We have Babel installed and ready to use, so let’s get some source files created. First create an HTML file to reference our source script and the babel-polyfill file:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Babel Test</title>
    <meta name="description" content="Babel Test Site" />
    <meta name="author" content="Ben Hofferber" />
    <script src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>
  </head>

  <body>
    <div id="appendToMe"></div>
    <script src="script.js"></script>
  </body>
</html>

For our source script, we’re going to use a couple of new ES6 features. Let’s define const and let variables and also use string interpolation to place a variable right into our text content:

;(function (window, document) {
  "use strict"

  const NAME = "Ben Hofferber"

  let div = document.getElementById("appendToMe")
  let h1 = document.createElement("h1")
  h1.textContent = `Hello ${NAME}!`

  div.appendChild(h1)
})(window, document)

Loading up the HTML file in a browser might work for you at this point. That’s probably because you’re using a ES6 compatible browser. If you’re running Internet Explorer 11 you should see a compilation error on the string interpolation. We’ll use babel to fix this by adding a new command to our package.json scripts:

{
  "scripts": {
    "transpile": "babel script.js --out-file script-compiled.js --source-maps --presets=es2015"
  }
}

When we run this we get two new files: ['script-compiled.js', 'script-compiled.js.map']

In order to use these files we’ll need to update the HTML reference to use the new compiled JavaScript file (not the map). Once this is done, test it out in Internet Explorer and Chrome just to make sure that everything is working. Also try out debugging through the source file by dropping a breakpoint. Notice that the file you are working with is the source file and not the Babel-generated one! Pretty slick!

All and all, Babel is a great tool to use to take advantage of the new features coming to JavaScript.

Hope you enjoy programming in the future today!