JavaScript
Article

Understanding ES6 Modules

By Sandeep Panda

Modules are one of the most important features of any programming language. Sadly, JavaScript lacks this very basic feature. But, that doesn’t stop us from writing modular code. We have two important standards, namely CommonJS and Asynchronous Module Definition (AMD) which let developers use modules in JavaScript. But, the next JavaScript version, known as ECMAScript 6, brings modules into JavaScript officially. Yes, modules are first class citizens in ES6. So, this article will give you a basic overview of how modules are used in ES6. In the end we will also see how to transpile your ES6 modules to ES5 so that they work in today’s browsers.

Basics

In ES6 each module is defined in its own file. The functions or variables defined in a module are not visible outside unless you explicitly export them. This means that you can write code in your module and only export those values which should be accessed by other parts of your app.

ES6 modules are declarative in nature. To export certain variables from a module you just use the keyword export. Similarly, to consume the exported variables in a different module you use import.

Working With a Simple Module

Let’s create a simple module that has two utility functions:

  1. generateRandom() : Generates a random number.
  2. sum() : Adds two numbers.

Next, let’s create a file named utility.js for the module:

utility.js

function generateRandom() {
    return Math.random();
}

function sum(a, b) {
    return a + b;
}

export { generateRandom, sum }

That’s it! The export keyword on the last line exports the two functions. As you can see, the exported functions are listed in curly braces separated by a comma. You can also rename the values while exporting like this:

export {generateRandom as random, sum as doSum}

Now, let’s see how to consume the exported values in a different module.

app.js

import { generateRandom, sum } from 'utility';

console.log(generateRandom()); //logs a random number
console.log(sum(1, 2)); //3

Note the first line. This imports the exported values from the module utility. If you want to import a single value (for example sum), you can do it by writing the following:

import { sum } from 'utility';

You can also import the entire module as an object and access exported values as properties. So, we can modify our code as following:

import 'utility' as utils;

console.log(utils.generateRandom()); //logs a random number
console.log(utils.sum(1, 2)); //3

Pretty simple, right? This was all about named exports. Now let’s see how to work with default exports.

Default Exports and Re-exporting

If you want to export a single value from the module then you can use default export. To demonstrate the usage of default exports let’s modify the utility module as shown below:

utility.js

var utils = {
  generateRandom: function() {
    return Math.random();    
  },
  sum: function(a, b) {
    return a + b;
  }
};

export default utils;

The last line just exports the object utils. It can be consumed as following in a different module:

app.js

import utils from 'utility';

console.log(utils.generateRandom()); //logs a random number
console.log(utils.sum(1, 2)); //3
export default utils; //exports the imported value

The first line simply imports the utils object exported previously. Once you import a value you can also re-export it. The last line in the above code does that.

This was the basic overview of ES6 modules. Now let’s see how to transpile the above ES6 modules to ES5 code so that we can run and test the code.

Using the ES6 Module Transpiler

The ES6 Module Transpiler is a tool that takes your ES6 module and compiles it into ES5 compatible code in the CommonJS or AMD style. You can install it via npm using the following command:

npm install -g es6-module-transpiler

Before proceeding grab our demo module’s source code from GitHub. The project structure is shown below:

es6-modules
    scripts/
        app.js
        utility.js
    out/

The directory scripts holds our ES6 modules. We will compile these modules and place them into the out directory. Go to the es6-modules directory in the terminal and type:

compile-modules convert -I scripts -o out app.js utility.js --format commonjs

The above command instructs the transpiler to compile the modules into CommonJS format and place them in the out directory. Once compilation is done the compiled modules will look like this:

out/app.js

Object.seal(exports);
var utility$$ = require("utility");

//logs a random number
console.log(utility$$.generateRandom());

console.log(utility$$.sum(1,2));

out/utility.js

Object.seal(Object.defineProperties(exports, {
    generateRandom: {
        get: function() {
            return generateRandom;
        },
        enumerable: true
    },
    sum: {
        get: function() {
            return sum;
        },
        enumerable: true
    }
}));

function generateRandom(){
    return Math.random();
}

function sum(a,b){
    return a+b;
}

To run this with node you need to do the following minor tweak in app.js so that Node can discover the module utility:

Change require("utility"); to require("./utility.js");.

Now you can just type the following in terminal and check out the output:

cd out
node app.js

You may also try compiling the modules into RequireJS (AMD) format and run in the browser.

Conclusion

ES6 modules are definitely powerful. Although support is not available everywhere yet, you can play with ES6 code today and transpile into ES5. You can also use Grunt, Gulp, or something similar to compile the modules during a build process. Further source maps can be used to debug the apps easily.

  • rahilwazir

    I thought Firefox should have implemented the export/import keywords.

  • Victor Miguez

    Great post, dude! :D

  • http://viii.in/ Vinay Raghu

    Been wanting a clear explanation on module exports for a while now. Just stumbled on your article…thanks for clearly explaining

  • kb

    I’ve been looking for an explanation of what es6 modules solve that CommonJS and Require don’t. Any thoughts on that? Nothing in this article makes es6 modules look any different than the aforementioned.

  • ChandrajeetMaurya

    Thanks , nice and simple explanation with example.

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in JavaScript, once a week, for free.