DEV Community

Robert Marshall
Robert Marshall

Posted on • Originally published at robertmarshall.dev on

ES6 Modules: A Beginner’s Guide


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:

&lt;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>
Enter fullscreen mode Exit fullscreen mode

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.

Importing packages with ES6 modules

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 = () => {}
Enter fullscreen mode Exit fullscreen mode

This allows the someFunction to be exported as a named function.

Default function

const anotherPackage = () => {}
export default anotherPackage
Enter fullscreen mode Exit fullscreen mode

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.

How to load ES6 modules in browser

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": {
        "..."
    }
}
Enter fullscreen mode Exit fullscreen mode

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)