ES6 Modules with System JS

Using ES6 modules today

With the arrival of the latest version of JavaScript, ECMAScript version 6, we have access to some very useful features, such as the ability to properly modularise our JavaScript.

Being able to use JavaScript modules is important, as it means that we can build applications (both for the browser and that run in the backend, e.g. using Node) that have a number of benefits, including:

being more self-contained, and less likely to cause side-effects in other code

less reliance on exposing and consuming global variables

being easier to test, as we can use dependency injection to mock our dependencies

better architecture of our applications

better access to code created by other parties

Existing solutions

Because JavaScript has not had native support for modules, a number of solutions have sprung up over the years to provide this, including:

All of these solutions are in wide use, and there's plenty of code out there that has been written to use one or more of the above solutions; particularly, there's a wealth of CommonJS modules available on NPM (more than 120,000 at the time this post was written).

The Problem

Ideally, we'd start using and creating ES6 Modules today; however it's going to be some time before all browsers implement the specification, and for those of us who have to support older browser versions such as IE8, we'd really like a solution that we can use now.

Also, although we may create new code using the ES6 modules format, we may also want to take advantage of the other modules formats, particularly CommonJS, so we can build off the efforts of others.

So, in short we want a solution that will let us use all of the major existing module solutions, along with ES6 modules, in the browsers used by our audience today.

The Solution

SystemJS is a project that meets our needs, in that it acts as a polyfill for the ES6 module specification, but also lets us make use of AMD and CommonJS modules as well as our IIFEs.

SystemJS bills itself as a universal dynamic module loader, and is designed as a wrapper around the es6-module-loader, a project which is also maintained by the SystemJS creator, Guy Bedford.

The good news is that we can make use of SystemJS and the es6-module-loader to provide wide support for all major JavaScript module formats, so that we can start developing applications now that allow us to work flexibly with existing code and third party modules.

Building our Bundle

For our example app, we want to create a bundle of modules — that is, a single file that can be downloaded by a browser, but which contains all of our custom modules that we expect to use in our application.

To achieve this, we make use of the SystemJS builder as follows (note that the following presumes that you're familiar with using build tools such as Grunt or Gulp):

The ES6 modules specification provides plenty of ways to expose functionality from a given module, though in the above case we take the approach of simply exposing the main object, meaning that our consuming module has access to all methods and variables defined on the object, though in the above example it won't have access to msgText.

Note that the only code we need code in our HTML is the app.js; all other modules are loaded via app.js.

Going Further

If you want to explore an app that demonstrates the above, check out this codepen.

Notes

As some of this technology is still relatively new, there are probably going to be a few wrinkles. In our experience, once we worked things out SystemJS worked well, but we did run across a strange bug in IE8, where at least some of the modules wouldn't load, but then did as soon as the developer tools were opened (and kept loading when the developer tools were closed again).