Skip to content

Commit bf9e61c

Browse files
doc: update and improve the CommonJS page
These changes: - update outdated info (`module.buildinModules` includes all built-ins since 23.5.0) - fix various typos - improve consistency - polish and make more clear some sentences
1 parent 43ffcf1 commit bf9e61c

File tree

1 file changed

+83
-79
lines changed

1 file changed

+83
-79
lines changed

doc/api/modules.md

Lines changed: 83 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ By default, Node.js will treat the following as CommonJS modules:
9191
interpreted.
9292

9393
* Files with an extension that is not `.mjs`, `.cjs`, `.json`, `.node`, or `.js`
94-
(when the nearest parent `package.json` file contains a top-level field
95-
[`"type"`][] with a value of `"module"`, those files will be recognized as
94+
when the nearest parent `package.json` file contains a top-level field
95+
[`"type"`][] with a value of `"module"` (those files will be recognized as
9696
CommonJS modules only if they are being included via `require()`, not when
9797
used as the command-line entry point of the program).
9898

@@ -109,7 +109,7 @@ When a file is run directly from Node.js, `require.main` is set to its
109109
`module`. That means that it is possible to determine whether a file has been
110110
run directly by testing `require.main === module`.
111111

112-
For a file `foo.js`, this will be `true` if run via `node foo.js`, but
112+
For example given a file `foo.js`, this will be `true` if run via `node foo.js`, but
113113
`false` if run by `require('./foo')`.
114114

115115
When the entry point is not a CommonJS module, `require.main` is `undefined`,
@@ -208,8 +208,8 @@ regarding which files are parsed as ECMAScript modules.
208208
3. The file has a `.js` extension, the closest `package.json` does not contain
209209
`"type": "commonjs"`, and the module contains ES module syntax.
210210

211-
If the ES Module being loaded meet the requirements, `require()` can load it and
212-
return the module namespace object. In this case it is similar to dynamic
211+
If the ES Module being loaded meets the requirements, `require()` can load it and
212+
return the [module namespace object][]. In this case it is similar to dynamic
213213
`import()` but is run synchronously and returns the name space object
214214
directly.
215215

@@ -253,8 +253,8 @@ This property is experimental and can change in the future. It should only be us
253253
by tools converting ES modules into CommonJS modules, following existing ecosystem
254254
conventions. Code authored directly in CommonJS should avoid depending on it.
255255

256-
When a ES Module contains both named exports and a default export, the result returned by `require()`
257-
is the module namespace object, which places the default export in the `.default` property, similar to
256+
When an ES Module contains both named exports and a default export, the result returned by `require()`
257+
is the [module namespace object][], which places the default export in the `.default` property, similar to
258258
the results returned by `import()`.
259259
To customize what should be returned by `require(esm)` directly, the ES Module can export the
260260
desired value using the string name `"module.exports"`.
@@ -346,7 +346,7 @@ require(X) from module at path Y
346346
a. return the core module
347347
b. STOP
348348
2. If X begins with '/'
349-
a. set Y to be the file system root
349+
a. set Y to the file system root
350350
3. If X begins with './' or '/' or '../'
351351
a. LOAD_AS_FILE(Y + X)
352352
b. LOAD_AS_DIRECTORY(Y + X)
@@ -357,14 +357,6 @@ require(X) from module at path Y
357357
6. LOAD_NODE_MODULES(X, dirname(Y))
358358
7. THROW "not found"
359359
360-
MAYBE_DETECT_AND_LOAD(X)
361-
1. If X parses as a CommonJS module, load X as a CommonJS module. STOP.
362-
2. Else, if the source code of X can be parsed as ECMAScript module using
363-
<a href="esm.md#resolver-algorithm-specification">DETECT_MODULE_SYNTAX defined in
364-
the ESM resolver</a>,
365-
a. Load X as an ECMAScript module. STOP.
366-
3. THROW the SyntaxError from attempting to parse X as CommonJS in 1. STOP.
367-
368360
LOAD_AS_FILE(X)
369361
1. If X is a file, load X as its file extension format. STOP
370362
2. If X.js is a file,
@@ -373,20 +365,17 @@ LOAD_AS_FILE(X)
373365
1. MAYBE_DETECT_AND_LOAD(X.js)
374366
c. If the SCOPE/package.json contains "type" field,
375367
1. If the "type" field is "module", load X.js as an ECMAScript module. STOP.
376-
2. If the "type" field is "commonjs", load X.js as an CommonJS module. STOP.
368+
2. If the "type" field is "commonjs", load X.js as a CommonJS module. STOP.
377369
d. MAYBE_DETECT_AND_LOAD(X.js)
378370
3. If X.json is a file, load X.json to a JavaScript Object. STOP
379371
4. If X.node is a file, load X.node as binary addon. STOP
380372
381-
LOAD_INDEX(X)
382-
1. If X/index.js is a file
383-
a. Find the closest package scope SCOPE to X.
384-
b. If no scope was found, load X/index.js as a CommonJS module. STOP.
385-
c. If the SCOPE/package.json contains "type" field,
386-
1. If the "type" field is "module", load X/index.js as an ECMAScript module. STOP.
387-
2. Else, load X/index.js as an CommonJS module. STOP.
388-
2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
389-
3. If X/index.node is a file, load X/index.node as binary addon. STOP
373+
MAYBE_DETECT_AND_LOAD(X)
374+
1. If X parses as a CommonJS module, load X as a CommonJS module. STOP.
375+
2. If the source code of X can be parsed as an ECMAScript module using
376+
<a href="esm.md#resolver-algorithm-specification">DETECT_MODULE_SYNTAX defined in
377+
the ESM resolver</a>, Load X as an ECMAScript module. STOP.
378+
3. THROW the SyntaxError from attempting to parse X as CommonJS in 1. STOP.
390379
391380
LOAD_AS_DIRECTORY(X)
392381
1. If X/package.json is a file,
@@ -399,6 +388,16 @@ LOAD_AS_DIRECTORY(X)
399388
g. THROW "not found"
400389
2. LOAD_INDEX(X)
401390
391+
LOAD_INDEX(X)
392+
1. If X/index.js is a file
393+
a. Find the closest package scope SCOPE to X.
394+
b. If no scope was found, load X/index.js as a CommonJS module. STOP.
395+
c. If the SCOPE/package.json contains "type" field,
396+
1. If the "type" field is "module", load X/index.js as an ECMAScript module. STOP.
397+
2. Else, load X/index.js as a CommonJS module. STOP.
398+
2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
399+
3. If X/index.node is a file, load X/index.node as binary addon. STOP
400+
402401
LOAD_NODE_MODULES(X, START)
403402
1. let DIRS = NODE_MODULES_PATHS(START)
404403
2. for each DIR in DIRS:
@@ -472,8 +471,8 @@ will not cause the module code to be executed multiple times. This is an
472471
important feature. With it, "partially done" objects can be returned, thus
473472
allowing transitive dependencies to be loaded even when they would cause cycles.
474473

475-
To have a module execute code multiple times, export a function, and call that
476-
function.
474+
To have a module execute code multiple times, move such code into an exported function
475+
and call that function.
477476

478477
### Module caching caveats
479478

@@ -488,7 +487,7 @@ Additionally, on case-insensitive file systems or operating systems, different
488487
resolved filenames can point to the same file, but the cache will still treat
489488
them as different modules and will reload the file multiple times. For example,
490489
`require('./foo')` and `require('./FOO')` return two different objects,
491-
irrespective of whether or not `./foo` and `./FOO` are the same file.
490+
irrespective of whether or not `./foo` and `./FOO` point to the same file.
492491

493492
## Built-in modules
494493

@@ -516,9 +515,11 @@ by that name.
516515

517516
Some built-in modules are always preferentially loaded if their identifier is
518517
passed to `require()`. For instance, `require('http')` will always
519-
return the built-in HTTP module, even if there is a file by that name. The list
520-
of built-in modules that can be loaded without using the `node:` prefix is exposed
521-
in [`module.builtinModules`][], listed without the prefix.
518+
return the built-in HTTP module, even if there is a file by that name.
519+
520+
The list of all the built-in modules can be retrieved from [`module.builtinModules`][].
521+
The modules being all listed without the `node:` prefix, except those that mandate such
522+
prefix (as explained in the next section).
522523

523524
### Built-in modules with mandatory `node:` prefix
524525

@@ -532,8 +533,6 @@ taken the name. Currently the built-in modules that requires the `node:` prefix
532533
* [`node:test`][]
533534
* [`node:test/reporters`][]
534535

535-
The list of these modules is exposed in [`module.builtinModules`][], including the prefix.
536-
537536
## Cycles
538537

539538
<!--type=misc-->
@@ -543,9 +542,9 @@ executing when it is returned.
543542

544543
Consider this situation:
545544

546-
`a.js`:
547-
548545
```js
546+
// a.js
547+
549548
console.log('a starting');
550549
exports.done = false;
551550
const b = require('./b.js');
@@ -554,9 +553,9 @@ exports.done = true;
554553
console.log('a done');
555554
```
556555

557-
`b.js`:
558-
559556
```js
557+
// b.js
558+
560559
console.log('b starting');
561560
exports.done = false;
562561
const a = require('./a.js');
@@ -565,20 +564,22 @@ exports.done = true;
565564
console.log('b done');
566565
```
567566

568-
`main.js`:
569-
570567
```js
568+
// main.js
569+
571570
console.log('main starting');
572571
const a = require('./a.js');
573572
const b = require('./b.js');
574573
console.log('in main, a.done = %j, b.done = %j', a.done, b.done);
575574
```
576575

577-
When `main.js` loads `a.js`, then `a.js` in turn loads `b.js`. At that
578-
point, `b.js` tries to load `a.js`. In order to prevent an infinite
579-
loop, an **unfinished copy** of the `a.js` exports object is returned to the
580-
`b.js` module. `b.js` then finishes loading, and its `exports` object is
581-
provided to the `a.js` module.
576+
Where `main.js` loads `a.js`, then `a.js` in turn loads `b.js`, and
577+
`b.js` loads `a.js`.
578+
579+
In order to prevent an infinite loop, an **unfinished copy** of the
580+
`a.js` exports object is returned to the `b.js` module. `b.js` then
581+
finishes loading, and its `exports` object is provided to the `a.js`
582+
module.
582583

583584
By the time `main.js` has loaded both modules, they're both finished.
584585
The output of this program would thus be:
@@ -618,12 +619,12 @@ A required module prefixed with `'/'` is an absolute path to the file. For
618619
example, `require('/home/marco/foo.js')` will load the file at
619620
`/home/marco/foo.js`.
620621

621-
A required module prefixed with `'./'` is relative to the file calling
622+
A required module prefixed with `'./'` or `'../'` is relative to the file calling
622623
`require()`. That is, `circle.js` must be in the same directory as `foo.js` for
623624
`require('./circle')` to find it.
624625

625626
Without a leading `'/'`, `'./'`, or `'../'` to indicate a file, the module must
626-
either be a core module or is loaded from a `node_modules` folder.
627+
either be a core module or being loaded from a `node_modules` folder.
627628

628629
If the given path does not exist, `require()` will throw a
629630
[`MODULE_NOT_FOUND`][] error.
@@ -677,13 +678,13 @@ folders as modules, and work for both `require` and `import`.
677678

678679
If the module identifier passed to `require()` is not a
679680
[built-in](#built-in-modules) module, and does not begin with `'/'`, `'../'`, or
680-
`'./'`, then Node.js starts at the directory of the current module, and
681+
`'./'`, then Node.js starts at the directory of the current module,
681682
adds `/node_modules`, and attempts to load the module from that location.
682683
Node.js will not append `node_modules` to a path already ending in
683684
`node_modules`.
684685

685-
If it is not found there, then it moves to the parent directory, and so
686-
on, until the root of the file system is reached.
686+
If it is not found there, then Node.js moves to the parent directory and repeats
687+
the process until either the module is found or the root of the file system is reached.
687688

688689
For example, if the file at `'/home/ry/projects/foo.js'` called
689690
`require('bar.js')`, then Node.js would look in the following locations, in
@@ -741,7 +742,7 @@ folder. These will be loaded faster, and more reliably.
741742

742743
<!-- type=misc -->
743744

744-
Before a module's code is executed, Node.js will wrap it with a function
745+
Before a CommonJS module's code is executed, Node.js will wrap it with a function
745746
wrapper that looks like the following:
746747

747748
```js
@@ -805,24 +806,24 @@ See [`__dirname`][] for the directory name of the current module.
805806

806807
Examples:
807808

808-
Running `node example.js` from `/Users/mjr`
809+
* Running `node example.js` from `/Users/mjr`
809810

810-
```js
811-
console.log(__filename);
812-
// Prints: /Users/mjr/example.js
813-
console.log(__dirname);
814-
// Prints: /Users/mjr
815-
```
811+
```js
812+
console.log(__filename);
813+
// Prints: /Users/mjr/example.js
814+
console.log(__dirname);
815+
// Prints: /Users/mjr
816+
```
816817

817-
Given two modules: `a` and `b`, where `b` is a dependency of
818-
`a` and there is a directory structure of:
818+
* Given two modules: `a` and `b`, where `b` is a dependency of
819+
`a` and there is a directory structure of:
819820

820-
* `/Users/mjr/app/a.js`
821-
* `/Users/mjr/app/node_modules/b/b.js`
821+
* `/Users/mjr/app/a.js`
822+
* `/Users/mjr/app/node_modules/b/b.js`
822823

823-
References to `__filename` within `b.js` will return
824-
`/Users/mjr/app/node_modules/b/b.js` while references to `__filename` within
825-
`a.js` will return `/Users/mjr/app/a.js`.
824+
References to `__filename` within `b.js` will return
825+
`/Users/mjr/app/node_modules/b/b.js` while references to `__filename` within
826+
`a.js` will return `/Users/mjr/app/a.js`.
826827

827828
### `exports`
828829

@@ -871,15 +872,17 @@ the current working directory. The relative paths of POSIX style are resolved
871872
in an OS independent fashion, meaning that the examples above will work on
872873
Windows in the same way they would on Unix systems.
873874

875+
Example:
876+
874877
```js
875878
// Importing a local module with a path relative to the `__dirname` or current
876-
// working directory. (On Windows, this would resolve to .\path\myLocalModule.)
879+
// working directory. (On Windows, this would resolve to .\path\myLocalModule)
877880
const myLocalModule = require('./path/myLocalModule');
878881

879882
// Importing a JSON file:
880883
const jsonData = require('./path/filename.json');
881884

882-
// Importing a module from node_modules or Node.js built-in module:
885+
// Importing a module from node_modules or a Node.js built-in module:
883886
const crypto = require('node:crypto');
884887
```
885888

@@ -1001,10 +1004,10 @@ changes:
10011004
is checked from this location.
10021005
* Returns: {string}
10031006

1004-
Use the internal `require()` machinery to look up the location of a module,
1005-
but rather than loading the module, just return the resolved filename.
1007+
Uses the internal `require()` machinery to look up the location of a module,
1008+
but rather than loading the module, just returns the resolved filename.
10061009

1007-
If the module can not be found, a `MODULE_NOT_FOUND` error is thrown.
1010+
If the module can not be found, a [`MODULE_NOT_FOUND`][] error is thrown.
10081011

10091012
##### `require.resolve.paths(request)`
10101013

@@ -1084,19 +1087,19 @@ a.on('ready', () => {
10841087
```
10851088

10861089
Assignment to `module.exports` must be done immediately. It cannot be
1087-
done in any callbacks. This does not work:
1088-
1089-
`x.js`:
1090+
done in any callbacks. For example this does not work:
10901091

10911092
```js
1093+
// x.js
1094+
10921095
setTimeout(() => {
10931096
module.exports = { a: 'hello' };
10941097
}, 0);
10951098
```
10961099

1097-
`y.js`:
1098-
10991100
```js
1101+
// y.js
1102+
11001103
const x = require('./x');
11011104
console.log(x.a);
11021105
```
@@ -1209,7 +1212,7 @@ deprecated:
12091212

12101213
The module that first required this one, or `null` if the current module is the
12111214
entry point of the current process, or `undefined` if the module was loaded by
1212-
something that is not a CommonJS module (E.G.: REPL or `import`).
1215+
something that is not a CommonJS module (e.g.: REPL or `import`).
12131216

12141217
### `module.path`
12151218

@@ -1269,9 +1272,9 @@ This section was moved to
12691272

12701273
* <a id="modules_module_findsourcemap_path_error" href="module.html#modulefindsourcemappath">`module.findSourceMap(path)`</a>
12711274
* <a id="modules_class_module_sourcemap" href="module.html#class-modulesourcemap">Class: `module.SourceMap`</a>
1272-
* <a id="modules_new_sourcemap_payload" href="module.html#new-sourcemappayload">`new SourceMap(payload)`</a>
1273-
* <a id="modules_sourcemap_payload" href="module.html#sourcemappayload">`sourceMap.payload`</a>
1274-
* <a id="modules_sourcemap_findentry_linenumber_columnnumber" href="module.html#sourcemapfindentrylinenumber-columnnumber">`sourceMap.findEntry(lineNumber, columnNumber)`</a>
1275+
* <a id="modules_new_sourcemap_payload" href="module.html#new-sourcemappayload">`new SourceMap(payload)`</a>
1276+
* <a id="modules_sourcemap_payload" href="module.html#sourcemappayload">`sourceMap.payload`</a>
1277+
* <a id="modules_sourcemap_findentry_linenumber_columnnumber" href="module.html#sourcemapfindentrylinenumber-columnnumber">`sourceMap.findEntry(lineNumber, columnNumber)`</a>
12751278

12761279
[Determining module system]: packages.md#determining-module-system
12771280
[ECMAScript Modules]: esm.md
@@ -1299,6 +1302,7 @@ This section was moved to
12991302
[`process.features.require_module`]: process.md#processfeaturesrequire_module
13001303
[`require.main`]: #requiremain
13011304
[exports shortcut]: #exports-shortcut
1305+
[module namespace object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#module_namespace_object
13021306
[module resolution]: #all-together
13031307
[native addons]: addons.md
13041308
[subpath exports]: packages.md#subpath-exports

0 commit comments

Comments
 (0)