ECMAScript Modules | Node.js v8.6.0 Documentation

Node.js

- About these Docs
- Usage & Example

- Assertion Testing
- Async Hooks
- Buffer
- C++ Addons
- C/C++ Addons - N-API
- Child Processes
- Cluster
- Command Line Options
- Console
- Crypto
- Debugger
- Deprecated APIs
- DNS
- Domain
- ECMAScript Modules
- Errors
- Events
- File System
- Globals
- HTTP
- HTTP/2
- HTTPS
- Inspector
- Internationalization
- Modules
- Net
- OS
- Path
- Performance Hooks
- Process
- Punycode
- Query Strings
- Readline
- REPL
- Stream
- String Decoder
- Timers
- TLS/SSL
- Tracing
- TTY
- UDP/Datagram
- URL
- Utilities
- V8
- VM
- ZLIB

- GitHub Repo & Issue Tracker
- Mailing List

# ECMAScript Modules#

Stability: 1 - Experimental

Node.js contains support for ES Modules based upon the Node.js EP for ES Modules.

Not all features of the EP are complete and will be landing as both VM support and implementation is ready. Error messages are still being polished.

## Enabling#

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.mjs

## Features#

### Supported#

Only the CLI argument for the main entry point to the program can be an entry point into an ESM graph. In the future `import()` can be used to create entry points into ESM graphs at run time.

### Unsupported#

Feature | Reason
--- | ---
`require('./foo.mjs')` | ES Modules have differing resolution and timing, use language standard `import()`
`import()` | pending newer V8 release used in Node.js
`import.meta` | pending V8 implementation
Loader Hooks | pending Node.js EP creation/consensus

## Notable differences between `import` and `require`#

### No NODE_PATH#

`NODE_PATH` is not part of resolving `import` specifiers. Please use symlinks if this behavior is desired.

### No `require.extensions`#

`require.extensions` is not used by `import`. The expectation is that loader hooks can provide this workflow in the future.

### No `require.cache`#

`require.cache` is not used by `import`. It has a separate cache.

### URL based paths#

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?query=1'; // loads ./foo with query of "?query=1"
    import './foo?query=2'; // loads ./foo with query of "?query=2"

For now, only modules using the `file:` protocol can be loaded.

## Interop with existing modules#

All CommonJS, JSON, and C++ modules can be used with `import`.

Modules loaded this way will only be loaded once, even if their query or fragment string differs between `import` statements.

When loaded via `import` these modules will provide a single `default` export representing the value of `module.exports` at the time they finished evaluating.

    import fs from 'fs';
    fs.readFile('./foo.txt', (err, body) => {
      if (err) {
        console.error(err);
      } else {
        console.log(body);
      }
    });