Introduction to ES Modules
By Flavio Copes
Learn how ES Modules let JavaScript files export and import values in browsers and Node.js, using default exports, named exports, and module specifiers.
ES Modules are the standard JavaScript module system. They let one file export values and another file import them.
Modern browsers and Node.js support ES Modules. The same import and export syntax works in both environments, although each environment resolves package names differently.
The MDN modules guide is the best complete reference for browser modules.
Export a value
Create a file named uppercase.js:
export default function uppercase(string) {
return string.toUpperCase()
}
This module has one default export.
Import it from another module:
import uppercase from './uppercase.js'
console.log(uppercase('hello')) //'HELLO'
You can choose the local name of a default import.
Named exports
A module can export several named values:
const first = 1
const second = 2
export { first, second }
Import the values by name:
import { first, second } from './numbers.js'
You can rename an import:
import { second as two } from './numbers.js'
Or import all named exports into a module namespace object:
import * as numbers from './numbers.js'
console.log(numbers.first)
The import * from './numbers.js' syntax is not valid. A namespace import always needs a local name after as.
The MDN import reference lists every supported import form.
Use modules in the browser
Load the entry module with type="module":
<script type="module" src="index.js"></script>
Module scripts use strict mode automatically and are deferred by default. Their dependencies are fetched before the module runs.
In browser code, relative module specifiers need ./ or ../:
import { first } from './numbers.js'
Root-relative and full URL imports also work:
import { first } from '/modules/numbers.js'
import { first } from 'https://cdn.example.org/numbers.js'
A bare name such as this does not identify a browser URL on its own:
import packageName from 'package-name'
Browsers can resolve bare names when you provide an import map. Bundlers and other runtimes also have their own package resolution rules.
Browser modules use CORS. Serve your files through a local web server while developing instead of opening the page with a file:// URL.
Use ES Modules in Node.js
Node treats .mjs files as ES Modules.
You can also add "type": "module" to package.json so Node treats .js files in that package as ES Modules:
{
"type": "module"
}
Use .cjs for a CommonJS file inside a module package.
Node can also detect module syntax in some ambiguous .js files, but an explicit "type" field is clearer and avoids extra parsing work. The Node.js package documentation explains the complete rules.
Related posts about js: