Skip to content

Commit a6758d1

Browse files
aduh95danielleadams
authored andcommitted
doc: clarify module system selection
Refs: #41345 (comment) PR-URL: #41383 Reviewed-By: Guy Bedford <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]>
1 parent db17a52 commit a6758d1

File tree

6 files changed

+137
-23
lines changed

6 files changed

+137
-23
lines changed

doc/api/cli.md

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Command-line options
1+
# Command-line API
22

33
<!--introduced_in=v5.9.1-->
44

@@ -11,16 +11,43 @@ To view this documentation as a manual page in a terminal, run `man node`.
1111

1212
## Synopsis
1313

14-
`node [options] [V8 options] [script.js | -e "script" | -] [--] [arguments]`
14+
`node [options] [V8 options] [<program-entry-point> | -e "script" | -] [--] [arguments]`
1515

16-
`node inspect [script.js | -e "script" | <host>:<port>] …`
16+
`node inspect [<program-entry-point> | -e "script" | <host>:<port>] …`
1717

1818
`node --v8-options`
1919

2020
Execute without arguments to start the [REPL][].
2121

2222
For more info about `node inspect`, see the [debugger][] documentation.
2323

24+
## Program entry point
25+
26+
The program entry point is a specifier-like string. If the string is not an
27+
absolute path, it's resolved as a relative path from the current working
28+
directory. That path is then resolved by [CommonJS][] module loader. If no
29+
corresponding file is found, an error is thrown.
30+
31+
If a file is found, its path will be passed to the [ECMAScript module loader][]
32+
under any of the following conditions:
33+
34+
* The program was started with a command-line flag that forces the entry
35+
point to be loaded with ECMAScript module loader.
36+
* The file has an `.mjs` extension.
37+
* The file does not have a `.cjs` extension, and the nearest parent
38+
`package.json` file contains a top-level [`"type"`][] field with a value of
39+
`"module"`.
40+
41+
Otherwise, the file is loaded using the CommonJS module loader. See
42+
[Modules loaders][] for more details.
43+
44+
### ECMAScript modules loader entry point caveat
45+
46+
When loading [ECMAScript module loader][] loads the program entry point, the `node`
47+
command will only accept as input only files with `.js`, `.mjs`, or `.cjs`
48+
extensions; and with `.wasm` extensions when
49+
[`--experimental-wasm-modules`][] is enabled.
50+
2451
## Options
2552

2653
<!-- YAML
@@ -269,8 +296,8 @@ Enable experimental JSON support for the ES Module loader.
269296
added: v9.0.0
270297
-->
271298

272-
Specify the `module` of a custom experimental [ECMAScript Module loader][].
273-
`module` may be either a path to a file, or an ECMAScript Module name.
299+
Specify the `module` of a custom experimental [ECMAScript module loader][].
300+
`module` may be any string accepted as an [`import` specifier][].
274301

275302
### `--experimental-policy`
276303

@@ -1900,14 +1927,18 @@ $ node --max-old-space-size=1536 index.js
19001927
```
19011928

19021929
[Chrome DevTools Protocol]: https://chromedevtools.github.io/devtools-protocol/
1903-
[ECMAScript Module loader]: esm.md#loaders
1930+
[CommonJS]: modules.md
1931+
[ECMAScript module loader]: esm.md#loaders
1932+
[Modules loaders]: packages.md#modules-loaders
19041933
[REPL]: repl.md
19051934
[ScriptCoverage]: https://chromedevtools.github.io/devtools-protocol/tot/Profiler#type-ScriptCoverage
19061935
[Source Map]: https://sourcemaps.info/spec.html
19071936
[Subresource Integrity]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
19081937
[V8 JavaScript code coverage]: https://v8project.blogspot.com/2017/12/javascript-code-coverage.html
1938+
[`"type"`]: packages.md#type
19091939
[`--cpu-prof-dir`]: #--cpu-prof-dir
19101940
[`--diagnostic-dir`]: #--diagnostic-dirdirectory
1941+
[`--experimental-wasm-modules`]: #--experimental-wasm-modules
19111942
[`--heap-prof-dir`]: #--heap-prof-dir
19121943
[`--openssl-config`]: #--openssl-configfile
19131944
[`--redirect-warnings`]: #--redirect-warningsfile
@@ -1920,6 +1951,7 @@ $ node --max-old-space-size=1536 index.js
19201951
[`dns.lookup()`]: dns.md#dnslookuphostname-options-callback
19211952
[`dns.setDefaultResultOrder()`]: dns.md#dnssetdefaultresultorderorder
19221953
[`dnsPromises.lookup()`]: dns.md#dnspromiseslookuphostname-options
1954+
[`import` specifier]: esm.md#import-specifiers
19231955
[`process.setUncaughtExceptionCaptureCallback()`]: process.md#processsetuncaughtexceptioncapturecallbackfn
19241956
[`tls.DEFAULT_MAX_VERSION`]: tls.md#tlsdefault_max_version
19251957
[`tls.DEFAULT_MIN_VERSION`]: tls.md#tlsdefault_min_version

doc/api/esm.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,12 @@ provides interoperability between them and its original module format,
9292

9393
<!-- type=misc -->
9494

95-
Node.js treats JavaScript code as CommonJS modules by default.
96-
Authors can tell Node.js to treat JavaScript code as ECMAScript modules
95+
Node.js has two module systems: [CommonJS][] modules and ECMAScript modules.
96+
97+
Authors can tell Node.js to use the ECMAScript modules loader
9798
via the `.mjs` file extension, the `package.json` [`"type"`][] field, or the
98-
`--input-type` flag. See
99-
[Modules: Packages](packages.md#determining-module-system) for more
100-
details.
99+
[`--input-type`][] flag. Outside of those cases, Node.js will use the CommonJS
100+
module loader. See [Determining module system][] for more details.
101101

102102
<!-- Anchors to make sure old links find a target -->
103103

@@ -1458,6 +1458,7 @@ success!
14581458
[CommonJS]: modules.md
14591459
[Conditional exports]: packages.md#conditional-exports
14601460
[Core modules]: modules.md#core-modules
1461+
[Determining module system]: packages.md#determining-module-system
14611462
[Dynamic `import()`]: https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports
14621463
[ES Module Integration Proposal for WebAssembly]: https://github.com/webassembly/esm-integration
14631464
[Import Assertions]: #import-assertions
@@ -1469,6 +1470,7 @@ success!
14691470
[WHATWG JSON modules specification]: https://html.spec.whatwg.org/#creating-a-json-module-script
14701471
[`"exports"`]: packages.md#exports
14711472
[`"type"`]: packages.md#type
1473+
[`--input-type`]: cli.md#--input-typetype
14721474
[`ArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
14731475
[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
14741476
[`TypedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray

doc/api/modules.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,38 @@ module.exports = class Square {
6161
};
6262
```
6363

64-
The module system is implemented in the `require('module')` module.
64+
The CommonJS module system is implemented in the [`module` core module][].
65+
66+
## Enabling
67+
68+
<!-- type=misc -->
69+
70+
Node.js has two module systems: CommonJS modules and [ECMAScript modules][].
71+
72+
By default, Node.js will treat the following as CommonJS modules:
73+
74+
* Files with a `.cjs` extension;
75+
76+
* Files with a `.js` extension when the nearest parent `package.json` file
77+
contains a top-level field [`"type"`][] with a value of `"commonjs"`.
78+
79+
* Files with a `.js` extension when the nearest parent `package.json` file
80+
doesn't contain a top-level field [`"type"`][]. Package authors should include
81+
the [`"type"`][] field, even in packages where all sources are CommonJS. Being
82+
explicit about the `type` of the package will make things easier for build
83+
tools and loaders to determine how the files in the package should be
84+
interpreted.
85+
86+
* Files with an extension that is not `.mjs`, `.cjs`, `.json`, `.node`, or `.js`
87+
(when the nearest parent `package.json` file contains a top-level field
88+
[`"type"`][] with a value of `"module"`, those files will be recognized as
89+
CommonJS modules only if they are being `require`d, not when used as the
90+
command-line entry point of the program).
91+
92+
See [Determining module system][] for more details.
93+
94+
Calling `require()` always use the CommonJS module loader. Calling `import()`
95+
always use the ECMAScript module loader.
6596

6697
## Accessing the main module
6798

@@ -1043,13 +1074,15 @@ This section was moved to
10431074
[ECMAScript Modules]: esm.md
10441075
[GLOBAL_FOLDERS]: #loading-from-the-global-folders
10451076
[`"main"`]: packages.md#main
1077+
[`"type"`]: packages.md#type
10461078
[`ERR_REQUIRE_ESM`]: errors.md#err_require_esm
10471079
[`Error`]: errors.md#class-error
10481080
[`__dirname`]: #__dirname
10491081
[`__filename`]: #__filename
10501082
[`import()`]: https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports
10511083
[`module.children`]: #modulechildren
10521084
[`module.id`]: #moduleid
1085+
[`module` core module]: module.md
10531086
[`module` object]: #the-module-object
10541087
[`package.json`]: packages.md#nodejs-packagejson-field-definitions
10551088
[`path.dirname()`]: path.md#pathdirnamepath

doc/api/packages.md

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,13 @@ along with a reference for the [`package.json`][] fields defined by Node.js.
5151
## Determining module system
5252

5353
Node.js will treat the following as [ES modules][] when passed to `node` as the
54-
initial input, or when referenced by `import` statements within ES module code:
54+
initial input, or when referenced by `import` statements or `import()`
55+
expressions:
5556

56-
* Files ending in `.mjs`.
57+
* Files with an `.mjs` extension.
5758

58-
* Files ending in `.js` when the nearest parent `package.json` file contains a
59-
top-level [`"type"`][] field with a value of `"module"`.
59+
* Files with a `.js` extension when the nearest parent `package.json` file
60+
contains a top-level [`"type"`][] field with a value of `"module"`.
6061

6162
* Strings passed in as an argument to `--eval`, or piped to `node` via `STDIN`,
6263
with the flag `--input-type=module`.
@@ -67,12 +68,13 @@ field, or string input without the flag `--input-type`. This behavior is to
6768
preserve backward compatibility. However, now that Node.js supports both
6869
CommonJS and ES modules, it is best to be explicit whenever possible. Node.js
6970
will treat the following as CommonJS when passed to `node` as the initial input,
70-
or when referenced by `import` statements within ES module code:
71+
or when referenced by `import` statements, `import()` expressions, or
72+
`require()` expressions:
7173

72-
* Files ending in `.cjs`.
74+
* Files with a `.cjs` extension.
7375

74-
* Files ending in `.js` when the nearest parent `package.json` file contains a
75-
top-level field [`"type"`][] with a value of `"commonjs"`.
76+
* Files with a `.js` extension when the nearest parent `package.json` file
77+
contains a top-level field [`"type"`][] with a value of `"commonjs"`.
7678

7779
* Strings passed in as an argument to `--eval` or `--print`, or piped to `node`
7880
via `STDIN`, with the flag `--input-type=commonjs`.
@@ -83,6 +85,48 @@ future-proof the package in case the default type of Node.js ever changes, and
8385
it will also make things easier for build tools and loaders to determine how the
8486
files in the package should be interpreted.
8587

88+
### Modules loaders
89+
90+
Node.js has two systems for resolving a specifier and loading modules.
91+
92+
There is the CommonJS module loader:
93+
94+
* It is fully synchronous.
95+
* It is responsible for handling `require()` calls.
96+
* It is monkey patchable.
97+
* It supports [folders as modules][].
98+
* When resolving a specifier, if no exact match is found, it will try to add
99+
extensions (`.js`, `.json`, and finally `.node`) and then attempt to resolve
100+
[folders as modules][].
101+
* It treats `.json` as JSON text files.
102+
* `.node` files are interpreted as compiled addon modules loaded with
103+
`process.dlopen()`.
104+
* It treats all files that lack `.json` or `.node` extensions as JavaScript
105+
text files.
106+
* It cannot be used to load ECMAScript modules (although it is possible to
107+
[load ECMASCript modules from CommonJS modules][]). When used to load a
108+
JavaScript text file that is not an ECMAScript module, it loads it as a
109+
CommonJS module.
110+
111+
There is the ECMAScript module loader:
112+
113+
* It is asynchronous.
114+
* It is responsible for handling `import` statements and `import()` expressions.
115+
* It is not monkey patchable, can be customized using [loader hooks][].
116+
* It does not support folders as modules, directory indexes (e.g.
117+
`'./startup/index.js'`) must be fully specified.
118+
* It does no extension searching. A file extension must be provided
119+
when the specifier is a relative or absolute file URL.
120+
* It can load JSON modules, but an import assertion is required (behind
121+
`--experimental-json-modules` flag).
122+
* It accepts only `.js`, `.mjs`, and `.cjs` extensions for JavaScript text
123+
files.
124+
* It can be used to load JavaScript CommonJS modules. Such modules
125+
are passed through the `es-module-lexer` to try to identify named exports,
126+
which are available if they can be determined through static analysis.
127+
Imported CommonJS modules have their URLs converted to absolute
128+
paths and are then loaded via the CommonJS module loader.
129+
86130
### `package.json` and file extensions
87131

88132
Within a package, the [`package.json`][] [`"type"`][] field defines how
@@ -1281,6 +1325,9 @@ This field defines [subpath imports][] for the current package.
12811325
[`esm`]: https://github.com/standard-things/esm#readme
12821326
[`package.json`]: #nodejs-packagejson-field-definitions
12831327
[entry points]: #package-entry-points
1328+
[folders as modules]: modules.md#folders-as-modules
1329+
[load ECMASCript modules from CommonJS modules]: modules.md#the-mjs-extension
1330+
[loader hooks]: esm.md#loaders
12841331
[self-reference]: #self-referencing-a-package-using-its-name
12851332
[subpath exports]: #subpath-exports
12861333
[subpath imports]: #subpath-imports

doc/api/synopsis.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,6 @@ Now, open any preferred web browser and visit `http://127.0.0.1:3000`.
8888
If the browser displays the string `Hello, World!`, that indicates
8989
the server is working.
9090

91-
[Command-line options]: cli.md#command-line-options
91+
[Command-line options]: cli.md#options
9292
[Installing Node.js via package manager]: https://nodejs.org/en/download/package-manager/
9393
[web server]: http.md

tools/doc/links-mapper.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"doc/api/synopsis.md": {
3-
"command line options": "cli.html#command-line-options",
3+
"command line options": "cli.html#options",
44
"web server": "http.html"
55
}
6-
}
6+
}

0 commit comments

Comments
 (0)