skull

Robert Tamayo

R
B
blog
skull

ES6 Javascript Features and Modules Using Rollup, Babel, and Uglify

By now, almost all browsers support es6 JavaScript modules, but because Internet Explorer still doesn't support them, I needed to find a backwards compatible solution. In addition, other es6 features such as arrow functions aren't supported by Internet Explorer, and Uglify has trouble minifying files with new es6 features such as "let".  For all of these reasons, I use a Grunt workflow that involves Rollup, Babel, and Uglify to get my files friendly across all browsers.

For this post, I made a simple repo that demonstrates the technique I use: https://github.com/robertttamayo/js-grunt-test.

This simple project uses modules, string literals, and arrow functions, which are incompatible with not only Internet Explorer but also uglify.

In app.js:

import * as Shape from "./lib/shape";
import * as Color from "./lib/color";
In shape.js:
import {render} from "./template";
let _target = '.locator-banner';
let _data = {
    triangle: 3,
    square: 4,
    pentagon: 5
}
const _template = `
    <div class="shape-message">
        <div>A triangle has {{triangle}} sides</div>
        <div>A square has {{square}} sides</div>
        <div>A pentagon has {{pentagon}} sides</div>
    </div>
`;
export let init = (data = _data) => {
    let _html = render(_template, data);
    document.getElementById("shape-message").innerHTML = _html;
};

To get this to work in one minified, es5 compatible javascript file, we need to do the following:

1. Rollup

Rollup is a module bundler that lets you use es6 javascript modules as if every browser could support them. The truth is that this is very close to being possible without Rollup, but because we are only "very" close – and not "there" – we need to use Rollup.

I'm using grunt-rollup as found here: https://www.npmjs.com/package/grunt-rollup. The full documentation for using Rollup can be found on its main site, https://rollupjs.org/guide/en.

In order to use grunt-rollup, we need to configure our package.json file. This also contains the other grunt plugins we'll be using.

{
    "name": "RedCodeBlueCode",
    "version": "0.1.0",
    "devDependencies": {
        "babel-cli": "latest",
        "babel-preset-env": "^1.7.0",
        "grunt": "latest",
        "grunt-babel": "latest",
        "grunt-rollup": "latest",
        "grunt-contrib-uglify": "latest",
        "grunt-contrib-watch": "latest"
    }
}

The configuration in Gruntfile.js is as follows:

rollup: {
    options: {},
    files: {
        dest: 'assets/js/rollup/bundle.js',
        src: 'assets/js/app.js'
    }
}

It's probably lame that I'm not using any options, but this is just a basic setup that works as intended. Notice that I'm putting bundle.js in the rollup/ directory, which means this folder shouldn't make it to production.
 
2. Babel

Babel is well known as the tool that lets us use awesome futuristic javascript in the mediocre present. I'm particularly interested in its ability to transpile es6-and-above javascript into es5 javascript, since this is what regular Uglify requires to minify all of our javascript files.

I'm using grunt-babel, which can be found here: https://www.npmjs.com/package/grunt-babel. All of the information about Babel is found here: https://babeljs.io/.

Here's my very simple grunt-babel config in Gruntfile.js:

babel: {
    options: {
        sourceMap: false,
        presets: [
            [
                "env",
                {
                    "targets": {
                        "browsers": [
                            "last 2 versions"
                        ]
                    },
                    "forceAllTransforms": true // this line turns "let" into "var", etc
                }
            ]
        ]
    },
    dist: {
        files: {
            'assets/js/babel/scripts.js': 'assets/js/rollup/bundle.js',
        }
    }
}

The coolest feature that you should not ignore the "env" preset; it is very powerful and can be used for much more than what I'm using it for in the demo. The documentation is here: https://babeljs.io/docs/en/babel-preset-env.

It's worth checking out the babel/scripts.js file. It's pretty interesting to see what Babel turns all of the awesome es6 javascript into in order to make it work.

3. Uglify

To be honest, my journey to building this config began when Uglify threw an error the first time I tried to use "let" as a keyword. This led me to Babel, which, after trying to use modules, led me to Rollup.

Uglify is very simple to configure in Gruntfile.js:

uglify: {
    options: {
        compress: true,
        mangle: true,
        sourceMap: true
    },
    dist: {
        files: {
            'assets/js/min/scripts.min.js': 'assets/js/babel/scripts.js'
        }
    }
}

This brings us to the end. The 3 steps above outline everything needed to use JavaScript modules and es6 features, while still being able to use them in IE and with Uglify.
Comments:
Leave a Comment
Submit