Stability: 1 - Experimental
Node.js contains support for ES Modules based upon the Node.js EP for ES Modules and the ESM Minimal Kernel.
The minimal feature set is designed to be compatible with all potential future implementations. Expect major changes in the implementation including interoperability support, specifier resolution, and default behavior.
The --experimental-modules flag can be used to enable features for loading
ESM modules.
Once this has been set, files ending with .mjs will be able to be loaded
as ES Modules.
node --experimental-modules my-app.mjsOnly the CLI argument for the main entry point to the program can be an entry point into an ESM graph. Dynamic import can also be used to create entry points into ESM graphs at runtime.
- {Object}
The import.meta metaproperty is an Object that contains the following
property:
url{string} The absolutefile:URL of the module.
| Feature | Reason |
|---|---|
require('./foo.mjs') |
ES Modules have differing resolution and timing, use dynamic import |
ESM must have the .mjs extension.
You must provide a file extension when using the import keyword.
NODE_PATH is not part of resolving import specifiers. Please use symlinks
if this behavior is desired.
require.extensions is not used by import. The expectation is that loader
hooks can provide this workflow in the future.
require.cache is not used by import. It has a separate cache.
ESM are resolved and cached based upon URL
semantics. This means that files containing special characters such as # and
? need to be escaped.
Modules will be loaded multiple times if the import specifier used to resolve
them have a different query or fragment.
import './foo.mjs?query=1'; // loads ./foo.mjs with query of "?query=1"
import './foo.mjs?query=2'; // loads ./foo.mjs with query of "?query=2"For now, only modules using the file: protocol can be loaded.
CommonJS, JSON, and Native modules can be used with module.createRequireFromPath().
// cjs.js
module.exports = 'cjs';
// esm.mjs
import { createRequireFromPath as createRequire } from 'module';
import { fileURLToPath as fromPath } from 'url';
const require = createRequire(fromPath(import.meta.url));
const cjs = require('./cjs');
cjs === 'cjs'; // trueBuiltin modules will provide named exports of their public API, as well as a default export which can be used for, among other things, modifying the named exports. Named exports of builtin modules are updated when the corresponding exports property is accessed, redefined, or deleted.
import EventEmitter from 'events';
const e = new EventEmitter();import { readFile } from 'fs';
readFile('./foo.txt', (err, source) => {
if (err) {
console.error(err);
} else {
console.log(source);
}
});import fs, { readFileSync } from 'fs';
fs.readFileSync = () => Buffer.from('Hello, ESM');
fs.readFileSync === readFileSync;The resolver has the following properties:
- FileURL-based resolution as is used by ES modules
- Support for builtin module loading
- Relative and absolute URL resolution
- No default extensions
- No folder mains
- Bare specifier package resolution lookup through node_modules
The algorithm to resolve an ES module specifier is provided through ESM_RESOLVE:
ESM_RESOLVE(specifier, parentURL)
- Let resolvedURL be undefined.
- If specifier is a valid URL then,
- Set resolvedURL to the result of parsing and reserializing specifier as a URL.
- Otherwise, if specifier starts with "/", "./" or "../" then,
- Set resolvedURL to the URL resolution of specifier relative to parentURL.
- Otherwise,
- Note: specifier is now a bare specifier.
- Set resolvedURL the result of PACKAGE_RESOLVE(specifier, parentURL).
- If the file at resolvedURL does not exist then,
- Throw a Module Not Found error.
- Return resolvedURL.
PACKAGE_RESOLVE(packageSpecifier, parentURL)
- Assert: packageSpecifier is a bare specifier.
- If packageSpecifier is a Node.js builtin module then,
- Return the string "node:" concatenated with packageSpecifier.
- While parentURL contains a non-empty pathname,
- Set parentURL to the parent folder URL of parentURL.
- Let packageURL be the URL resolution of the string concatenation of parentURL, "/node_modules/" and "packageSpecifier".
- If the file at packageURL exists then,
- Return packageURL.
- Throw a Module Not Found error.