DEV Community

flavio ⚡️🔥
flavio ⚡️🔥

Posted on • Originally published at flaviocopes.com on

Introduction to ES Modules

ES Modules

  • Introduction to ES Modules
  • The ES Modules Syntax
  • Other import/export options
  • CORS
  • What about browsers that do not support modules?
  • Conclusion <!-- /TOC --> ## Introduction to ES Modules

ES Modules is the ECMAScript standard for working with modules.

While Node.js has been using the CommonJS standard since years, the browser never had a module system, as every major decision such as a module system must be first standardized by ECMAScript and then implemented by the browser.

This standardization process completed with ES6 and browsers started implementing this standard trying to keep everything well aligned, working all in the same way, and now ES Modules are supported in Chrome, Safari, Edge and Firefox (since version 60).

Modules are very cool, because they let you encapsulate all sorts of functionality, and expose this functionality to other JavaScript files, as libraries.

ES Modules Support

The ES Modules Syntax

The syntax to import a module is:

import package from 'module-name'

Enter fullscreen mode Exit fullscreen mode

while CommonJS uses

const package = require('module-name')

Enter fullscreen mode Exit fullscreen mode

A module is a JavaScript file that exports one or more value (objects, functions or variables), using the export keyword. For example, this module exports a function that returns a string uppercase:

uppercase.js

export default (str) => str.toUpperCase()

Enter fullscreen mode Exit fullscreen mode

In this example, the module defines a single, default export , so it can be an anonymous function. Otherwise it would need a name to distinguish it from other exports.

Now, any other JavaScript module can import the functionality offered by uppercase.js by importing it.

An HTML page can add a module by using a <script> tag with the special type="module" attribute:

<script type="module" src="index.js"></script>

Enter fullscreen mode Exit fullscreen mode

Note: this module import behaves like a defer script load. See efficiently load JavaScript with defer and async

It’s important to note that any script loaded with type="module" is loaded in strict mode.

In this example, the uppercase.js module defines a default export , so when we import it, we can assign it a name we prefer:

import toUpperCase from './uppercase.js'

Enter fullscreen mode Exit fullscreen mode

and we can use it:

toUpperCase('test') //'TEST'

Enter fullscreen mode Exit fullscreen mode

You can also use an absolute path for the module import, to reference modules defined on another domain:

import toUpperCase from 'https://flavio-es-modules-example.glitch.me/uppercase.js'

Enter fullscreen mode Exit fullscreen mode

This is also valid import syntax:

import {foo} from '/uppercase.js';
import {foo} from '../uppercase.js';

Enter fullscreen mode Exit fullscreen mode

This is not:

import {foo} from 'uppercase.js';
import {foo} from 'utils/uppercase.js';

Enter fullscreen mode Exit fullscreen mode

It’s either absolute, or has a ./ or / before the name.

Other import/export options

We saw this example above:

export default (str) => str.toUpperCase()

Enter fullscreen mode Exit fullscreen mode

This creates one default export. In a file however you can export more than one thing, by using this syntax:

const a = 1
const b = 2
const c = 3

export { a, b, c }

Enter fullscreen mode Exit fullscreen mode

Another module can import all those exports using

import * from 'module'

Enter fullscreen mode Exit fullscreen mode

You can import just a few of those exports, using the destructuring assignment:

import { a } from 'module'
import { a, b } from 'module'

Enter fullscreen mode Exit fullscreen mode

You can rename any import, for convenience, using as:

import { a, b as two } from 'module'

Enter fullscreen mode Exit fullscreen mode

You can import the default export, and any non-default export by name, like in this common React import:

import React, { Component } from "react"

Enter fullscreen mode Exit fullscreen mode

You can check an ES Modules example on https://glitch.com/edit/#!/flavio-es-modules-example?path=index.html

CORS

Modules are fetched using CORS. This means that if you reference scripts from other domains, they must have a valid CORS header that allows cross-site loading (like Access-Control-Allow-Origin: *)

What about browsers that do not support modules?

Use a combination of type="module" and nomodule:

<script type="module" src="module.js"></script>
<script nomodule src="fallback.js"></script>

Enter fullscreen mode Exit fullscreen mode

Conclusion

ES Modules are one of the biggest features introduced in modern browsers. They are part of ES6 but the road to implement them has been long.

We can now use them! But we must also remember that having more than a few modules is going to have a performance hit on our pages, as it’s one more step that the browser must perform at runtime.

Webpack is probably going to still be a huge player even if ES Modules land in the browser, but having such a feature directly built in the language is huge for a unification of how modules work in the client-side and on Node.js as well.

Top comments (0)