This article was originally posted (and is more up to date) at https://robertmarshall.dev/blog/es6-modules-a-beginners-guide/
ES6 Modules are a relatively new concept in the JavaScript world that have been gaining traction lately. If you’re not familiar with them, they essentially allow you to better organize your code and keep things clean and modular. In this post, we’re going to give you a beginner’s guide to using ES6 modules.
An ES6 module is a piece of JavaScript code that executes in strict mode only. It means that any variables or functions declared in the module won’t be added automatically to the global scope.
What are ES6 Modules?
ES6 modules are JavaScript modules that are used to import and export functions, objects, or primitive values from one file to another.
Previously
In the past it was not possible to directly reference one JavaScript file in another. To use a function from another file, that file would need to be already loaded within the DOM like so:
<script src="https://code.jquery.com/jquery-3.1.1.js"></script>
<script src="dist/random-util.js"></script>
<script src="dist/app.js"></script>
Although this isn’t necessarily “bad”, there are a couple of flaws in this approach.
The first is that the namespace gets polluted with global variables. Third party scripts and any utility function files have to be loaded first to make sure that any script that requires the functions have access to them. In the above example you can see that JQuery
and the random-util
have been loaded first so that app.js
has access to them.
The second is that we are unsure of our dependencies. We can only assume that the scripts that we need have been loaded. And the only way to make sure is launch the website and check everything works correctly.
With ES6 Modules
Now with ES6 modules, we can import packages and files into one main script without any need to check the ordering of imports (within reason) and we know immediately if a package has not been loaded correctly.
Everything inside an ES6 module is private by default. There is no need for use strict
as everything is already in strict mode. To make a variable or function public, the export
feature is used. This allows other modules to import it.
What is the different between Common JS and ES6 Modules?
Common JS and ES6 modules are very similar in their syntax. However they work in very different ways. Common JS is the original and default module system of Node.js. It uses require and module.exports as shown here:
// Importing modules
const somePackage = require('./somePackage');
const anotherPackage = require('./anotherPackage');
const ourFunction = (data) => {
const res = anotherPackage()
return somePackage.someFunction(res, data)
}
// Exporting our module
modules.exports = ourFunction
It is not possible to selectively load modules with require
. This means that every function within the somePackage file is loaded, whether it gets used or not. As well as this, all requires are synchronous meaning imports must processed one by one. Synchronous requires in CommonJS can pose a performance issue for large-scale applications with hundreds of modules.
Importing ES6 Modules
ES6 uses import and export. This means you only load the modules that you need, and the importing of the modules is asynchronous. ES6 Modules are generally more efficient with large scale applications due to the way that import modules. The below shows how the imports differ to the CommonJS way of doing things.
// Importing modules
import { someFunction } from './somePackage'
import anotherPackage from './anotherPackage'
const ourFunction = (data) => {
const res = anotherPackage()
return someFunction(res, data)
}
// Exporting our module
export default ourFunction
In the above code, someFunction
has been destructured from somePackage
as it is not the default export, but a named function. This allows multiple packages to be split out and imported. anotherPackage
has been imported without destructuring, this is due to it being the default import.
Exporting ES6 Modules
There are several ways to export ES6 modules. The above example shows two functions from packages being imported, one a default, and one a named function. The below code shows how these were set up and exported.
A named function
export const someFunction = () => {}
This allows the someFunction
to be exported as a named function.
Default function
const anotherPackage = () => {}
export default anotherPackage
This allows the function to be imported as a default function.
ES6 Modules in the Browser
When ES6 was first released in 2015 browsers were not able to run it. For this reason transpilers were needed to convert it to ES5. There are a number of tools that can be used for this, such as Webpack, Babel, and Gulp. However 2015 was quite a while ago in terms of technology, so where does that leave us now? Do we still need to transpile it?
This is still up for debate, and entirely depends on your use case and target market. CanIUse shows that ECMAScript 2015 (ES6) has a 98% support rate on modern browsers. The only thing to consider is if your users are based in companies that still use an outdated IE. Performance of ES6 is also far better than that of ES5. Better Programming has put together a very good argument of why the performance of ES6 is far better.
There is a slight difference in how ES6 Modules are loaded in the browser compared to ES5. ES5 uses the standard <script src="app.js"></script>
, whereas ES6 needs a little more.
How to use ES6 Modules in the Browser
In its bare bones, you load an ES6 file into a HTML file like so:
<script type="module" src="./app.js"></script>
However, something to keep in mind. Scripts using the of type module are deferred by default. You are able to override this behaviour though. Ghostcoder put together this really helpful example to show the flow of script execution, and which is loaded first.
ES6 Modules in Node.JS
Node.js has offered on-by-default support for ESM since v16. However, although ES Modules are now considered stable and ready for production use, the fact that there are two different module loading mechanisms makes it a little confusing to use both Common JS and ES6 Modules in Node.js.
How to use ES6 Modules in Node.js
To use ES6 in a new Node project is fairly straight forward, there is a little bit of boilerplate to set up and then you are good to go. Node doesn’t support import
and export
inside files that end with .js
. You have two options, the first is to use the file extension .mjs
, or modify packages.json
to include "type": "module"
. I.E.
{
"name": "my-package",
"type": "module",
"dependencies": {
"..."
}
}
Advantages of using ES6 Modules
There are a number of advantages to using ES6 Modules. The first is tree shaking. Although this is possible in CommonJS, is it far more performantive in ES6, and with ES6 the modules are initialized only once. Tree-shaking means that the final output of your code is smaller, which is important for speed on the frontend.
Top comments (0)