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 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 29 additions & 9 deletions doc/api/modules.md
Expand Up @@ -63,6 +63,15 @@ 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][] for more details.

## Accessing the main module

<!-- type=misc -->
Expand Down Expand Up @@ -133,10 +142,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 @@ -375,11 +387,15 @@ correctly within an application.

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`.
`.node`. When loading a file that has a different extension (e.g. `.cjs`), its
full name must be included, including its file extension (e.g.
`require('./file.cjs')`).

`.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,23 @@ 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
[`--input-type`]: cli.md#--input-typetype
[`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