ES6 modules are set to form the standard module format for the web. Instead of waiting around for browsers to support the new syntax, it is now possible to use them directly in all browsers today using the ES6 loader polyfill.

The great thing is that using the polyfill has very few tradeoffs in comparison to other module systems in the browser.

As soon as the ES6 specification is confirmed, polyfill approaches like this should be able to form the way forward for modular development in the browser. Note that the specification is still subject to change, thus this approach is not yet ready for production use.

The ES6 Loader

The polyfill can be included in the page with the single script tag:

 <script src="es6-module-loader.js"></script>

ES6 modules simply load JavaScript files that specify dependences and exports using the import and export module syntax.

For example, consider a widget which is dependent on jQuery.

widget.js:

import $ from 'jquery';

export function render(container) {
  var el = $('<div class="widget"></div>');
  $(el).click(function() {
    console.log('widget click');
  });
  $(container).append(el);
};

To load the widget, we can use the window.System default loader provided by the ES6 module API, allowing us to write:

<script>
  System.import('widget').then(function(widget) {
    widget.render(document.body);
  });
</script>

By default, the ES6 module loader will assume that these module names can be found at:

baseURL + '/' + moduleName + '.js'

So for this to work without any configuration we just need to ensure that we include the files widget.js and jquery.js in the same folder as our HTML page.

With the polyfill, the above will work identically to the spec, allowing the full use of ES6 modules today.

ES6 Loader Polyfill Approach

The loader polyfill provides the Loader, System and Module globals identically to the latest specification. It uses XHR to load the script, parses out the import and export statements, loads dependencies and executes the code.

The loader polyfill comes in two parts - a 17KB loader polyfill, which works with Traceur for ES6 parsing.

The Traceur parser is only loaded when module syntax is present, so that when loading non-module scripts, the polyfill need only be 17KB.

The idea is that builds would be used in production, just like every other module system today, to convert modules into a single script or set of scripts that simply define the modules directly.

These built files would be of the form:

System.set('jquery', new Module({
  'jQuery': ...
}));

The loader can then work seamlessly between production and development, allowing only the 10KB version to be used in production. Since all current module systems need a production build, the above is not actually such a high cost.