Hail, Babel! The Transpiling Overlord

I agree with Kyle Simpson in welcoming our new transpiling overlords.

“I for one welcome our new transpiling overlords. The web is not broken by ES6, it just got upgraded.” – Kyle Simpson in a comment on The ES6 Conundrum

In particular, I welcome the Babel overlord!

babelOverLord

I bow my knee to the great and powerful Babel. Of course, not everyone is ready to hail. I understand the hesitation. But let’s see if I can ease some of the cognitive fear.

In this Q&A, I hope to ease any anxiety around grokking or implementing JavaScript transpiling using Babel (formally called 6to5). By the end, it is my intention that you will be comfortable with the notion of a newer and better JavaScript via transpiling.

Q&A Overview:

Hold up, what is transpiling?

Transpiling is a type of compiling that takes source code written in one language and transforms it into a similar language, if not the same exact language. For example, Babel takes ES6 JavaScript code and “transpiles” it into ES5 JavaScript code.

Don’t confuse transpiling with compiling. Compiling typically involves transforming source code written in one language and compiling it into a completely different language.

When speaking about transpiling, just keep in mind we are talking about compiling source code, not into an entirely new language, but instead to a similar language.

Conceptually transpiling is similar to taking something like Sass, a CSS-like language extension, and converting it to actual CSS.

Why transpile?

The broad purpose of transpiling is to transform source code that wouldn’t run without transforming, to the state expected by the final interpreter/runtime. For example, using Babel, ES6+ code can be written during development then transpiled down to production code that can be interpreted by ES5 browsers/Node.

In other words, by transpiling, the limitations of the runtime environment do not directly dictate or control which language features one can employ during development. A developer can write ES6+ code today, then transpile it to ES5 for non-ES6 environments.

Why transpile ES6 to ES5?

Reason 1

Because ES6+ features are a significant upgrade that is long over due and makes the language better (e.g Modules, Collections, Generators etc.). Period!

In this case “better” is much much better because the new JavaScript can result in higher quality code that is easier to write and maintain. This, of course, matters because a better language pushes software towards the overall software goal of longevity.

Reason 2

Because transpiling enables the usage of potential updates to the language before they get standardized. This helps everyone in the long run.

Reason 3

Because transpiling opens up the possibility to pre-configured, community-driven, performance tweaks during the interim between ES5 and ES6.

Reason 4

Because, if it can be used to compile facebook.com, it might just work for your production app as well.

Why shouldn’t I transpile JavaScript?

Reason 1

Because you have to support a browser that is not considered an ES5 browser (i.e. < ie9). Also, the limited features, caveats, and additional polyfills that attempt to make this possible are not worth the complexity, overhead, or risk.

Transpiling might very well be limited to new projects, and ones that target modern browsers. Neither of which might work for you.

Reason 2

Because you have to have the highest performance available and transpiled code potentially prohibits this goal. This can occur in two ways. Either, by outputting extremely verbose/bloated code or slower code that, if written in ES5, would be neither.

Reason 3

Because reading and debugging transpiled code is a deal breaker. In other words, the code that runs in production was not directly written by a human and that’s just not acceptable, regardless of source maps.

Reason 4

Because you are un-willing to accept yet another build chore and degree of complexity. And, no way around it, transpiling is another step that adds complexity to a software system.

Reason 5

You author a solution for other developers and you simply don’t want to place a dependency on Babel for your users or potential contributers.

Do I really get everything ES6+ offers if I transpile?

No! You get a lot of ES6, but not everything. Transpiling does not straight-up give us everything ES6 offers, transformed to ES5. The unchangeable fact is that transpiling does not, and will not, ever provide an environment where everything works perfectly as specified by the current or future ECMAScript specifications.

What exactly is Babel?

Babel is a JavaScript trans-compiler tool/environment/platform that takes JavaScript source code with newer or next generation JavaScript features (i.e. ES6+) and, where it can, re-writes these features using older JavaScript language features (i.e. ES5) for the purpose of supporting older JavaScript environments.

For example, the ES6 code below demonstrates the use of default function parameters:

function greet(msg='hello', name='world') {
  console.log(msg,name);
}

greet();
// -> hello world
greet('hey');
// -> hey world

This can be transpiled down to the following ES5 code:

'use strict';

function greet() {
  var msg = arguments.length <= 0 || arguments[0] === undefined ? 'hello' : arguments[0];
  var name = arguments.length <= 1 || arguments[1] === undefined ? 'world' : arguments[1];

  console.log(msg, name);
}

greet();
// -> hello world
greet('hey');
// -> hey world

This is what Babel can do for you.

Note that Babel is not trying to be more than JavaScript. Babel does not subjectively try to improve the language. Babel is committed to JavaScript, and not an opinionated version of JavaScript. Babel is not trying to be a permanent fixture in your development work flow. In theory, when ES6 is fully supported by a modern browsers, you could stop using it.

In other words, by using Babel, you would have the option of removing it in the future because it plugs what is natively missing. No re-write down the road – the future is simply given to you today with the notion that your code is potentially future proof.

However, with that said, some developers think of Babel as a permanent solution that has no shelf life because transpiling means you can always get newer portions of the language before they go mainstream. Many think Babel will always be needed, especially since the new rate of change for JavaScript should be yearly rather by the decade.

For more insights into the types of changes to your code that Babel orchestrates have a look at “es6-equivalents-in-es5” Github repo or try converting some ES6 code to ES5 in real time online.

How exactly does one use Babel?

Remember, Babel is just a tool that takes ES6 code and transforms it into ES5 code. This tool can be used/implemented in several ways. The most common ways, in order, are listed below.

  1. By way of a build system (e.g. Gulp, jspm, Webpack) transforming ES6 development code, to ES5 production code, in real time during development.
  2. Install locally into a Node project from npm, require() from a module
  3. Install globally with npm, run from the command line
  4. By way of a framework that internally makes use of it (Ember, Meteor, Rails, Sails)

Note that any real world usage of Babel would entail having the transpiling occur before the code reaches production environments. In other words, transpiling at runtime (i.e. compiling in the browser) is possible, but is not intended for serious use.

Why do I need Babel?

You might not, but here are some reasons that might convince you that you do.

Reason 1

Because Babel currently is the most compliant ES6+ coding environment (71%) available today.

Reason 2

Because using as many updates to ES6 as soon as possible is too valuable in relation to code quality to wait on support/implementations by runtime environments (e.g. Browsers, Node, etc.).

Reason 3

Because unlike TypeScript, Dart, and CoffeeScript, Babel aligns itself with potential and current features in the JavaScript language itself. The aforementioned solutions go off the rails and get somewhat opinionated about the language outside of the accepted and proposed changes to JavaScript. In a sense, Babel is a true JavaScript platform while everything else that offers JavaScript transpiling uses a custom JavaScript platform.

Reason 4

Because Babel, under certain configurations, requires no runtime dependencies.

Reason 5

Because Babel, offers source maps that allow seamless debugging of your code, regardless of what it turns into after transpiling it.

Reason 6

Because Babel’s intentions are to offer newer standards ASAP before they are even standardized. This means you get to try them out before they get baked into the language.

Reason 7

Because Babel does not focus on solving a subjective coding preference, but instead on issues that all JavaScript developers share. For example, Babel exists to circumvent the fact that you might have to support older browsers but need newer features today. It does not mix into that basic goal other concerns that potentially could derail a developer in the future.

What’s the catch?

Like I said earlier, you don’t get a pure and flawless ES6 environment with Babel. For example, ES6 Proxies can’t be transpiled or polyfilled. In addition, several of the new ES6 parts are only partially supported by Babel (for example, Subclassable Built-ins and Tail Calls).

The reality is that it is impossible to implement every semantic at the same level of the JavaScript engine. So, the catch is you get the closest possible ES6-like environment possible, but the fact is it’s not the real thing.

What I think you need to know is that, if you are targeting a native ES5 environment, you’ll suffer from the least amount of caveats and partial support issues. The caveats, additional polyfills, and lack of support will increase if you have to support a polyfilled ES5 environment.

Should I use the ES7 proposed features?

For production, I’d steer away from anything that is not in the specification (i.e. stage 4). The experimental ECMAScript features can be test driven, but, given the odds of change, one should avoid coding towards an unknown future and wait until that future is known.

I need to support ES3 browsers, can Babel do that?

Bringing ES5 features to an ES3 browser was possible before Babel. While Babel does assume that you are using an ES5 environment in production, you can still plug everything up using the es5-shim along with the Babel polyfill (browser-polyfill.js can be found in the babel-core npm release).

The browser-polyfill.js file from Babel will emulate the fullest ES6 environment possible. And the es5-shim will bring ES3 browsers/environments to the ES5 table. Of course, you now have an entirely new set of caveats to deal with by shimming an ES3 JavaScript engine.

What will it cost performance wise by using Babel?

Performance thresholds will be different for different situations. So, it is difficult to generalize about this topic. I’d recommend reading about some of the performance implications to date and coming to your own conclusions on the topic.

  1. How much overhead does ES2015 bring on the client?
  2. Performance of ES6 features relative to the ES5 baseline operations per second

The short of it is, yes, you take on some performance hits. But the questions is, how much of a hit and is it even noticeable by your users? Always consider what you gain versus what you give up. Remember, slower is not bad unless the slowness actually has a verifiable/testable effect.

Can’t I just polyfill my way to ES7?

To some degree, yes. But Babel gets you close to the future with less caveats.

What are my other choices besides Babel?

I’d argue that whoever provides the most stable and compliant ES6 environment for development is the only choice. And that is Babel. Of course, this presupposes that getting new language features, not creating custom language features, is the objective.

Other choices are available that are similar to Babel. However, keep in mind these choices come with extra goals beyond bringing language compliant code (i.e. native features) and future features to you as soon as possible.

The most notable two are:

  • TypeScript (maybe in the future TypeScript will use Babel for transpiling)
  • Traceur

I’ll close this Q&A article with one last question. And I believe it to be the most important question.

How would you (i.e. me) use Babel?

Glad you asked. I would use it in combination with jspm and systemJS. I explain exactly how I would do this in a previous article I wrote called, “Choose ES6 modules Today!“.

Jump over to that article and start writing better JavaScript today using Babel!

Comments

  • Chris Weed

    Thanks for the great post! One question I did have about Babel is how does it migrate as browsers advance? So say Chrome doesn’t support feature X, but next week it does. Should I be updating Babel with every release so it can slowly transpile less of my ES6 code to ES5 (because it’s supported natively now).

    Or does Babel simply transpile everything to ES5 regardless if the browser it’s running in can handle portions of the ES6.

    • Have a look here: http://babeljs.io/docs/faq/

      Specifically, this:

      “Toggleable transformers

      With support for ES2015 being implemented into engines at a rapid rate it’s critical that certain transformations have the ability to be turned off. With Babel every single transformation can be turned off. Classes get supported in your target environment? Simply disable it and reap the benefits of all the other transformers.”