Skip to content

Commit 8429216

Browse files
aduh95BethGriggs
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 ef7c798 commit 8429216

File tree

6 files changed

+137
-23
lines changed

6 files changed

+137
-23
lines changed

doc/api/cli.md

+38-6
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
@@ -277,8 +304,8 @@ Enable experimental JSON support for the ES Module loader.
277304
added: v9.0.0
278305
-->
279306

280-
Specify the `module` of a custom experimental [ECMAScript Module loader][].
281-
`module` may be either a path to a file, or an ECMAScript Module name.
307+
Specify the `module` of a custom experimental [ECMAScript module loader][].
308+
`module` may be any string accepted as an [`import` specifier][].
282309

283310
### `--experimental-policy`
284311

@@ -1931,15 +1958,19 @@ $ node --max-old-space-size=1536 index.js
19311958
```
19321959

19331960
[Chrome DevTools Protocol]: https://chromedevtools.github.io/devtools-protocol/
1934-
[ECMAScript Module loader]: esm.md#loaders
1961+
[CommonJS]: modules.md
1962+
[ECMAScript module loader]: esm.md#loaders
1963+
[Modules loaders]: packages.md#modules-loaders
19351964
[OSSL_PROVIDER-legacy]: https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html
19361965
[REPL]: repl.md
19371966
[ScriptCoverage]: https://chromedevtools.github.io/devtools-protocol/tot/Profiler#type-ScriptCoverage
19381967
[Source Map]: https://sourcemaps.info/spec.html
19391968
[Subresource Integrity]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
19401969
[V8 JavaScript code coverage]: https://v8project.blogspot.com/2017/12/javascript-code-coverage.html
1970+
[`"type"`]: packages.md#type
19411971
[`--cpu-prof-dir`]: #--cpu-prof-dir
19421972
[`--diagnostic-dir`]: #--diagnostic-dirdirectory
1973+
[`--experimental-wasm-modules`]: #--experimental-wasm-modules
19431974
[`--heap-prof-dir`]: #--heap-prof-dir
19441975
[`--openssl-config`]: #--openssl-configfile
19451976
[`--redirect-warnings`]: #--redirect-warningsfile
@@ -1952,6 +1983,7 @@ $ node --max-old-space-size=1536 index.js
19521983
[`dns.lookup()`]: dns.md#dnslookuphostname-options-callback
19531984
[`dns.setDefaultResultOrder()`]: dns.md#dnssetdefaultresultorderorder
19541985
[`dnsPromises.lookup()`]: dns.md#dnspromiseslookuphostname-options
1986+
[`import` specifier]: esm.md#import-specifiers
19551987
[`process.setUncaughtExceptionCaptureCallback()`]: process.md#processsetuncaughtexceptioncapturecallbackfn
19561988
[`tls.DEFAULT_MAX_VERSION`]: tls.md#tlsdefault_max_version
19571989
[`tls.DEFAULT_MIN_VERSION`]: tls.md#tlsdefault_min_version

doc/api/esm.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,12 @@ provides interoperability between them and its original module format,
9393

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

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

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

@@ -1442,6 +1442,7 @@ success!
14421442
[CommonJS]: modules.md
14431443
[Conditional exports]: packages.md#conditional-exports
14441444
[Core modules]: modules.md#core-modules
1445+
[Determining module system]: packages.md#determining-module-system
14451446
[Dynamic `import()`]: https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports
14461447
[ES Module Integration Proposal for WebAssembly]: https://github.com/webassembly/esm-integration
14471448
[Import Assertions]: #import-assertions
@@ -1453,6 +1454,7 @@ success!
14531454
[WHATWG JSON modules specification]: https://html.spec.whatwg.org/#creating-a-json-module-script
14541455
[`"exports"`]: packages.md#exports
14551456
[`"type"`]: packages.md#type
1457+
[`--input-type`]: cli.md#--input-typetype
14561458
[`ArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
14571459
[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
14581460
[`TypedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray

doc/api/modules.md

+34-1
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

@@ -1047,13 +1078,15 @@ This section was moved to
10471078
[ECMAScript Modules]: esm.md
10481079
[GLOBAL_FOLDERS]: #loading-from-the-global-folders
10491080
[`"main"`]: packages.md#main
1081+
[`"type"`]: packages.md#type
10501082
[`ERR_REQUIRE_ESM`]: errors.md#err_require_esm
10511083
[`Error`]: errors.md#class-error
10521084
[`__dirname`]: #__dirname
10531085
[`__filename`]: #__filename
10541086
[`import()`]: https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports
10551087
[`module.children`]: #modulechildren
10561088
[`module.id`]: #moduleid
1089+
[`module` core module]: module.md
10571090
[`module` object]: #the-module-object
10581091
[`package.json`]: packages.md#nodejs-packagejson-field-definitions
10591092
[`path.dirname()`]: path.md#pathdirnamepath

doc/api/packages.md

+55-8
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
@@ -1236,6 +1280,9 @@ This field defines [subpath imports][] for the current package.
12361280
[`esm`]: https://github.com/standard-things/esm#readme
12371281
[`package.json`]: #nodejs-packagejson-field-definitions
12381282
[entry points]: #package-entry-points
1283+
[folders as modules]: modules.md#folders-as-modules
1284+
[load ECMASCript modules from CommonJS modules]: modules.md#the-mjs-extension
1285+
[loader hooks]: esm.md#loaders
12391286
[self-reference]: #self-referencing-a-package-using-its-name
12401287
[subpath exports]: #subpath-exports
12411288
[subpath imports]: #subpath-imports

doc/api/synopsis.md

+1-1
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

+2-2
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)