ES Modules is the standard method for working with modules in ECMAScript. While Node.js has been using the CommonJS standard for years, the browser did not have a native module system until the standardization of ES Modules in ES6. Now, ES Modules are supported in major browsers like Chrome, Safari, Edge, and Firefox (since version 60).
Modules are a powerful tool that allows you to encapsulate functionality and expose it to other JavaScript files as libraries. In this blog post, we will explore the basics of ES Modules and how to use them effectively.
The ES Modules Syntax
The syntax for importing a module in ES Modules is:
import package from 'module-name'
This is different from CommonJS, which uses:
const package = require('module-name')
An ES Module is a JavaScript file that exports one or more values (objects, functions, or variables) using the export
keyword. For example, a module can export a function that returns a string in uppercase:
export default str => str.toUpperCase()
To import functionality from a module, you can use a <script>
tag with the special attribute type="module"
in an HTML page:
<script type="module" src="index.js"></script>
It’s important to note that any script loaded with type="module"
is loaded in strict mode.
When importing a module, you can assign it a name of your choice:
import toUpperCase from './uppercase.js'
You can then use the imported functionality:
toUpperCase('test') //'TEST'
You can also import modules from other domains by using an absolute path:
import toUpperCase from 'https://flavio-es-modules-example.glitch.me/uppercase.js'
Other import/export options
In addition to default exports, ES Modules support named exports. You can export multiple values from a file using the following syntax:
const a = 1
const b = 2
const c = 3
export { a, b, c }
To import all the exports from a module, you can use the wildcard import:
import * as module from 'module'
You can also import only specific exports using destructuring assignment:
import { a } from 'module'
import { a, b } from 'module'
Furthermore, you can rename imports for convenience using the as
keyword:
import { a, b as two } from 'module'
In some cases, you may want to import the default export and specific non-default exports by name:
import React, { Component } from 'react'
CORS
ES Modules are fetched using CORS (Cross-Origin Resource Sharing). This means that if you reference scripts from other domains, they must have a valid CORS header that allows cross-site loading (e.g., Access-Control-Allow-Origin: *
).
What about browsers that do not support modules?
To handle browsers that do not support ES Modules, you can use a combination of type="module"
and the nomodule
attribute:
<script type="module" src="module.js"></script>
<script nomodule src="fallback.js"></script>
The browser will execute the module script if it supports ES Modules, otherwise it will execute the fallback script.
Conclusion
ES Modules are a significant addition to modern browsers, allowing developers to use a standardized module system both client-side and on Node.js. While having more modules can impact performance, the benefits of modularizing code and improved code organization make ES Modules a valuable feature.
Webpack will continue to be relevant even with the availability of ES Modules in browsers, but having a built-in module system in the language brings a unification to how modules work across different platforms.