|
| 1 | +# Modules |
| 2 | + |
| 3 | +<!--introduced_in=v9.x.x--> |
| 4 | + |
| 5 | +> Stability: 1 - Experimental |
| 6 | +
|
| 7 | +<!--name=esm--> |
| 8 | + |
| 9 | +Node contains support for ES Modules based upon [the Node EP for ES Modules](https://github.com/nodejs/node-eps/blob/master/002-es-modules.md). |
| 10 | + |
| 11 | +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. |
| 12 | + |
| 13 | +## Enabling |
| 14 | + |
| 15 | +<!-- type=misc --> |
| 16 | + |
| 17 | +The `--experimental-modules` flag can be used to enable features for loading ESM modules. |
| 18 | + |
| 19 | +Once this has been set, you can use files ending with `.mjs` as ES Modules. |
| 20 | + |
| 21 | +```sh |
| 22 | +node --experimental-modules my-app.mjs |
| 23 | +``` |
| 24 | + |
| 25 | +## Features |
| 26 | + |
| 27 | +<!-- type=misc --> |
| 28 | + |
| 29 | +### Supported |
| 30 | + |
| 31 | +Only the CLI argument for the main entry point to your program can be an entry point into an ESM graph. In the future you can use `import()` to create entry points into ESM graphs at run time. |
| 32 | + |
| 33 | +### Unsupported |
| 34 | + |
| 35 | +| Feature | Reason | |
| 36 | +| `require('./foo.mjs')` | ES Modules have differing resolution and timing, use language standard `import()` | |
| 37 | +| `import()` | pending newer V8 release used in Node.js | |
| 38 | +| `import.meta` | pending V8 implementation | |
| 39 | +| Loader Hooks | pending Node.js EP creation/consensus | |
| 40 | + |
| 41 | +## Notable differences between `import` and `require` |
| 42 | + |
| 43 | +### No NODE_PATH |
| 44 | + |
| 45 | +`NODE_PATH` is not part of resolving `import` specifiers. Please use symlinks if you need behavior like this. |
| 46 | + |
| 47 | +### No `require.extensions` |
| 48 | + |
| 49 | +`require.extensions` is not used by `import`. The expectation is that loader hooks can provide this workflow in the future. |
| 50 | + |
| 51 | +### No `require.cache` |
| 52 | + |
| 53 | +`require.cache` is not used by `import`. It has a separate cache. |
| 54 | + |
| 55 | +### URL based paths |
| 56 | + |
| 57 | +ESM are resolved and cached based upon [URL](url.spec.whatwg.org) semantics. This means that files containing special characters such as `#` and `?` need to be escaped. |
| 58 | + |
| 59 | +Modules will be loaded multiple times if the `import` specifier used to resolve them have a different query or fragment. |
| 60 | + |
| 61 | +```js |
| 62 | +import "./foo?query=1"; // loads ./foo with query of "?query=1" |
| 63 | +import "./foo?query=2"; // loads ./foo with query of "?query=2" |
| 64 | +``` |
| 65 | + |
| 66 | +For now, only modules using the `file:` protocol can be loaded. |
| 67 | + |
| 68 | +## Interop with existing modules |
| 69 | + |
| 70 | +All CommonJS, JSON, and C++ modules can be used with `import`. |
| 71 | + |
| 72 | +Modules loaded this way will only be loaded once, even if their query or fragment string differs between `import` statements. |
| 73 | + |
| 74 | +When loaded via `import` these modules will provide a single `default` export representing the value of `module.exports` at the time they finished evaluating. |
| 75 | + |
| 76 | +```js |
| 77 | +import fs from 'fs'; |
| 78 | +fs.readFile('./foo.txt', (err, body) { |
| 79 | + if (err) { |
| 80 | + console.error(err); |
| 81 | + } else { |
| 82 | + console.log(body); |
| 83 | + } |
| 84 | +}); |
| 85 | +``` |
0 commit comments