Introduction
Until recently if you wanted to take full advantage of modules in JavaScript you needed to make use of third party libraries. Tools like CommonJS (AMD), Browserify, Webpack and others have become widely utilised in recent years. These tools are very powerful but can be complex to implement.
A simple and standardised module system has so far proven elusive in JavaScript. I think it's one of the most important features that has remained missing from the core language.
The good news is ES6 Modules will change all this and will be supported in all modern browsers sooner than you may think.
Browser Support
- Safari 10.1+ — Support enabled by default
- Firefox 54+ — Support enabled via
about:config
- Chrome 60+ — Support enabled via
about:flags
- Edge 15 — Support enabled via
about:flags
- Opera 47 — Support enabled via
about:flags
Check out Can I use for the latest browser support information on ES6 modules.
As you can see, although not quite ready for prime time, ES6 modules will be available by default in all modern browsers very soon.
Using ES6 Modules
Here are some simple examples to demonstrate how to get started.
<!DOCTYPE html>
<html>
<head>
<title>ES6 module example</title>
<script src="app/utils.js" type="module"></script>
<script src="app/fallback.js" nomodule></script>
</head>
<body>
</body>
</html>
You can add module
to the type attribute of a script element <script type="module">
. The browser will then treat either inline or external script
elements as an ES6 module.
Browsers that support ES6 modules will ignore scripts with a nomodule
attribute. This is useful for providing a fallback script to legacy browsers.
It's worth noting that ES6 modules now have strict mode enabled by default.
Single Export
In utils.js file.
function hello() {
return "Hello";
}
function world() {
return "World";
}
// Basic export
export { hello, world };
In main.js file.
import {hello, world} from '/app/utils.js';
hello();
world();
Include a name space
import * as util from '/app/utils.js';
util.hello();
util.world();
Named Export
export function hello() {
return "Hello";
}
export function world() {
return "World";
}
Named exports can also export objects/function as and when you create them.
Default Export
In utils.js file.
var utils = {
hello: function() {
return "Hello";
},
world: function() {
return "World";
}
}
export default utils;
In main.js file.
import utils from '/app/utils.js';
utils.hello()
utils.world()
Gotchas
Be aware that there are a few differences between regular JS and JavaScript running in an ES6 module.
CORS — Module scripts are requested with CORS and should make use of valid CORS headers e.g.
Access-Control-Allow-Origin: *.
Use root relative paths to import modules —
import {foo} from '/utils/bar.js';
works.import {foo} from 'utils/bar.js';
doesn't work.Strict mode by default — ES6 modules run in strict mode (no
'use strict'
is required).The top level value of
this
isundefined
— not the window object.variables are local to the module — unless specifically exported.
Deferred by default — modules are non blocking and execute as
defer
scripts.
Further Information
Documentation from <abbr title="Mozilla Developer Network">MDN</abbr> and some more detailed examples: