Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: clarify require behavior with non .js extensions #41345

Merged
merged 8 commits into from
Jan 2, 2022
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions doc/api/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ module.exports = class Square {

The module system is implemented in the `require('module')` module.

## Enabling

<!-- type=misc -->

Node.js treats JavaScript code as CommonJS modules by default.
Authors can tell Node.js to treat JavaScript code as CommonJS modules
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems weird to say “it’s the default, and here’s how you can make it apply”.

For file extensions, .cjs is always CJS, .mjs is always ESM, .js is CJS by default (but type module can make this be ESM), and anything else is either .json, .node, .wasm, or “unknown” (which is treated as CJS). Piped input is CJS by default, but can be made ESM with the input-type flag.

Can we say something basically exactly like that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove this section from this PR and move it to a separate PR so it can be discussed separately if that's ok.

via the `.cjs` file extension, the `package.json` [`"type"`][] field, or the
`--input-type` flag. See
[Determining module system](packages.md#determining-module-system) for more
details.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Node.js treats JavaScript code as CommonJS modules by default.
Authors can tell Node.js to treat JavaScript code as CommonJS modules
via the `.cjs` file extension, the `package.json` [`"type"`][] field, or the
`--input-type` flag. See
[Determining module system](packages.md#determining-module-system) for more
details.
Node.js has two module systems: CommonJS and ES modules.
Node.js treats JavaScript code as CommonJS modules by default.
Within an ES module context, authors can tell Node.js to treat
JavaScript code as CommonJS modules via the `.cjs` file extension,
the `package.json` [`"type"`][] field, or the `--input-type` flag. See
[Determining module system](packages.md#determining-module-system) for more
details.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything is an es module context. Type module doesn’t create an “es module context”, it just changes the default parse goal for .js files.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess, put another way - what exactly is an “ES module context”? Within a filesystem, you can use extensions with or without the type module flag; in a command line, you can use the input-type flag.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand what would an ES module context mean either. Also, FWIW I've copied this section from esm.md, so if we want to change its wording maybe it's best to make a separate PR for that? I'm tempted to remove this change from this PR so it can be discussed separately. wdyt?

node/doc/api/esm.md

Lines 97 to 102 in 2bc1d92

Node.js treats JavaScript code as CommonJS modules by default.
Authors can tell Node.js to treat JavaScript code as ECMAScript modules
via the `.mjs` file extension, the `package.json` [`"type"`][] field, or the
`--input-type` flag. See
[Modules: Packages](packages.md#determining-module-system) for more
details.


## Accessing the main module

<!-- type=misc -->
Expand Down Expand Up @@ -133,10 +144,13 @@ relative, and based on the real path of the files making the calls to

## The `.mjs` extension

It is not possible to `require()` files that have the `.mjs` extension.
Attempting to do so will throw [an error][]. The `.mjs` extension is
reserved for [ECMAScript Modules][] which cannot be loaded via `require()`.
See [ECMAScript Modules][] for more details.
Due to the synchronous nature of `require()`, it is not possible to use it to
load ECMAScript module files. Attempting to do so will throw a
[`ERR_REQUIRE_ESM`][] error. Use [`import()`][] instead.

The `.mjs` extension is reserved for [ECMAScript Modules][] which cannot be
loaded via `require()`. See [Determining module system][] section for more info
regarding which files are parsed as ECMAScript modules.

## All together...

Expand Down Expand Up @@ -377,9 +391,11 @@ If the exact filename is not found, then Node.js will attempt to load the
required filename with the added extensions: `.js`, `.json`, and finally
`.node`.

`.js` files are interpreted as JavaScript text files, and `.json` files are
parsed as JSON text files. `.node` files are interpreted as compiled addon
modules loaded with `process.dlopen()`.
`.json` files are parsed as JSON text files, `.node` files are interpreted as
compiled addon modules loaded with `process.dlopen()`. Files using any other
extension (or no extension at all) are parsed as JavaScript text files. Refer to
the [Determining module system][] section to understand what parse goal will be
used.

aduh95 marked this conversation as resolved.
Show resolved Hide resolved
A required module prefixed with `'/'` is an absolute path to the file. For
example, `require('/home/marco/foo.js')` will load the file at
Expand Down Expand Up @@ -1036,19 +1052,22 @@ This section was moved to
* <a id="modules_sourcemap_payload" href="module.html#sourcemappayload">`sourceMap.payload`</a>
* <a id="modules_sourcemap_findentry_linenumber_columnnumber" href="module.html#sourcemapfindentrylinenumber-columnnumber">`sourceMap.findEntry(lineNumber, columnNumber)`</a>

[Determining module system]: packages.md#determining-module-system
[ECMAScript Modules]: esm.md
[GLOBAL_FOLDERS]: #loading-from-the-global-folders
[`"main"`]: packages.md#main
[`"type"`]: packages.md#type
[`ERR_REQUIRE_ESM`]: errors.md#err_require_esm
[`Error`]: errors.md#class-error
[`__dirname`]: #__dirname
[`__filename`]: #__filename
[`import()`]: https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports
[`module.children`]: #modulechildren
[`module.id`]: #moduleid
[`module` object]: #the-module-object
[`package.json`]: packages.md#nodejs-packagejson-field-definitions
[`path.dirname()`]: path.md#pathdirnamepath
[`require.main`]: #requiremain
[an error]: errors.md#err_require_esm
[exports shortcut]: #exports-shortcut
[module resolution]: #all-together
[native addons]: addons.md