Compiling Next Generation JavaScript (ES6, ES7, React) in Browser with Babel 6 and Above

Babel is an amazing tool for writing ES6 (ES2015), ES7 (ES2016), JSX, etc. code that finally gets compiled (or transpiled) into JavaScript (mostly ES5 as of now) that can be executed by most browsers. So basically you can use JS features like classes, promises, etc. without worrying about the browser support as Babel will eventually convert all your code into browser-understandable program.

Modularization in Babel 6 (Major Change)

With Babel 6, a lot of changes were made to the project. The biggest change has been code modularization. All the transformers have been broken into their own plugins and/or preset modules. So now by default, running a file through babel will just spit the same code as output. For transformation you’ll have to use the right plugins or presets. Here’s a list of all of the official ones.

So now if you want to watch a folder for changes and transpile React/JSX and ES2015 (ES6), then this is the brand new command:

# Install babel core and presets
$ npm install babel-core babel-preset-react babel-preset-es2015

# Install the babel command line tools that'll give access to the babel command too
$ npm install babel-cli -g

# Transformation with react and ES6 presets
$ babel --presets es2015 react src --watch --out-dir build

The new Node API is like this:

var result = require("babel-core").transform("code();", {
  presets: ["es2015", "react"]
});

result.code; // Generated code
result.map; // Source map
result.ast; // AST

To learn about further internal or setup related changes, feel free to go through these two short reads:

Coming Back to in-Browser Compilation

The deal is, babel-browser was deprecated and eventually removed, so now compiling a babel bundle for the browser is tricky and I noticed that the latest bundled babel libraries that you’ll find on CDNJS don’t work (throws JS errors). Babel now recommends using a bundler like webpack. This is what they have to say now about the removal:

Compiling in the browser has a fairly limited use case, so if you are working on a production site you should be precompiling your scripts server-side. See setup build systems for more information.

Fair enough, but there are times when you might need it, for instance online test cases on JSFiddle or JSBin. Thankfully, there’s still a repository called babel-standalone that is similar to babel-browser and can be used in non-Node.js (like browsers) environments.

Usage

Using it is fairly simple if you read the repo’s README file. Here’s a small HTML page with some React code (react and es2015 presets in use):

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>React App!</title>
    <script src="build/react.js"></script>
    <script src="build/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.6.5/babel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/babel">
      ReactDOM.render(
        <h1>Hello World!</h1>,
        document.getElementById('app')
      );
    </script>
    <script>
      // Get all the babel scripts
      var babel_scripts = document.querySelectorAll('script[type="text/babel"]');
      // Loop over them
      Array.prototype.forEach.call(babel_scripts, function (script, index, arr) {
        // Get their contents
        var input = script.textContent;
        // Transform/Transpile/Compile
        var output = Babel.transform( input, { presets: ['es2015', 'react'] }).code;

        // Create a new script tag of `javascript` type
        var new_script = document.createElement('script');
        new_script.setAttribute('type', 'text/javascript');
        // Set the contents of the script to the transpiled code
        new_script.textContent = output;

        // Remove the babel script
        script.remove();
        // Inject the new transpiled JS
        document.querySelector('body').appendChild(new_script);
      });
    </script>
  </body>
</html>

The library is loaded from CDNJS and then I’ve written some JS code that basically takes all the script tags with type="text/babel" and transpiles them using the global Babel object (Babel API) exposed by the library. Once the transpilation is done, new script tags are added with the final JS code that gets executed when inserted into the DOM.

One thing that it doesn’t take care of is external scripts. Surely you can extend my small snippet to accommodate for such feature requests.

Cheers!

Author: Rishabh

Rishabh is a full stack web and mobile developer from India. Follow me on Twitter.

2 thoughts on “Compiling Next Generation JavaScript (ES6, ES7, React) in Browser with Babel 6 and Above”

  1. The babel_scripts.forEach(function (script, index, arr) {} did not work for me, because babel_scripts (from document.querySelectorAll) is a Node List, not an array, so use of forEach gets: Uncaught TypeError: babel_scripts.forEach is not a function.
    Fixed it using:
    [].forEach.call(babel_scripts, function (script, index, arr) {}

Leave a Reply

Your email address will not be published. Required fields are marked *

*