@@ -142,46 +142,56 @@ CommonJS. This includes the following: |
142 | 142 | * Lexical redeclarations of the CommonJS wrapper variables (`require`, `module`, |
143 | 143 | `exports`, `__dirname`, `__filename`). |
144 | 144 |
|
145 | | -### Modules loaders |
146 | | - |
147 | | -Node.js has two systems for resolving a specifier and loading modules. |
148 | | - |
149 | | -There is the CommonJS module loader: |
150 | | - |
151 | | -* It is fully synchronous. |
152 | | -* It is responsible for handling `require()` calls. |
153 | | -* It is monkey patchable. |
154 | | -* It supports [folders as modules][]. |
155 | | -* When resolving a specifier, if no exact match is found, it will try to add |
156 | | - extensions (`.js`, `.json`, and finally `.node`) and then attempt to resolve |
157 | | - [folders as modules][]. |
158 | | -* It treats `.json` as JSON text files. |
159 | | -* `.node` files are interpreted as compiled addon modules loaded with |
160 | | - `process.dlopen()`. |
161 | | -* It treats all files that lack `.json` or `.node` extensions as JavaScript |
162 | | - text files. |
163 | | -* It can only be used to [load ECMAScript modules from CommonJS modules][] if |
164 | | - the module graph is synchronous (that contains no top-level `await`). |
165 | | - When used to load a JavaScript text file that is not an ECMAScript module, |
166 | | - the file will be loaded as a CommonJS module. |
167 | | - |
168 | | -There is the ECMAScript module loader: |
169 | | - |
170 | | -* It is asynchronous, unless it's being used to load modules for `require()`. |
171 | | -* It is responsible for handling `import` statements and `import()` expressions. |
172 | | -* It is not monkey patchable, can be customized using [loader hooks][]. |
173 | | -* It does not support folders as modules, directory indexes (e.g. |
174 | | - `'./startup/index.js'`) must be fully specified. |
175 | | -* It does no extension searching. A file extension must be provided |
176 | | - when the specifier is a relative or absolute file URL. |
177 | | -* It can load JSON modules, but an import type attribute is required. |
178 | | -* It accepts only `.js`, `.mjs`, and `.cjs` extensions for JavaScript text |
179 | | - files. |
180 | | -* It can be used to load JavaScript CommonJS modules. Such modules |
181 | | - are passed through the `cjs-module-lexer` to try to identify named exports, |
182 | | - which are available if they can be determined through static analysis. |
183 | | - Imported CommonJS modules have their URLs converted to absolute |
184 | | - paths and are then loaded via the CommonJS module loader. |
| 145 | +### Module resolution and loading |
| 146 | + |
| 147 | +Node.js has two types of module resolution and loading, chosen based on how the module is requested. |
| 148 | + |
| 149 | +When a module is requested via `require()` (available by default in CommonJS modules, |
| 150 | +and can be dynamically generated using `createRequire()` in both CommonJS and ES Modules): |
| 151 | + |
| 152 | +* Resolution: |
| 153 | + * The resolution initiated by `require()` supports [folders as modules][]. |
| 154 | + * When resolving a specifier, if no exact match is found, `require()` will try to add |
| 155 | + extensions (`.js`, `.json`, and finally `.node`) and then attempt to resolve |
| 156 | + [folders as modules][]. |
| 157 | + * It does not support URLs as specifiers by default. |
| 158 | +* Loading: |
| 159 | + * `.json` files are treated as JSON text files. |
| 160 | + * `.node` files are interpreted as compiled addon modules loaded with `process.dlopen()`. |
| 161 | + * `.ts`, `.mts` and `.cts` files are treated as [TypeScript][] text files. |
| 162 | + * Files with any other extension, or without extensions, are treated as JavaScript |
| 163 | + text files. |
| 164 | + * `require()` can only be used to [load ECMAScript modules from CommonJS modules][] if |
| 165 | + the [ECMAScript module][ES Module] _and its dependencies_ are synchronous |
| 166 | + (i.e. they do not contain top-level `await`). |
| 167 | + |
| 168 | +When a module is requested via static `import` statements (only available in ES Modules) |
| 169 | +or `import()` expressions (available in both CommonJS and ES Modules): |
| 170 | + |
| 171 | +* Resolution: |
| 172 | + * The resolution of `import`/`import()` does not support folders as modules, |
| 173 | + directory indexes (e.g. `'./startup/index.js'`) must be fully specified. |
| 174 | + * It does not perform extension searching. A file extension must be provided |
| 175 | + when the specifier is a relative or absolute file URL. |
| 176 | + * It supports `file://` and `data:` URLs as specifiers by default. |
| 177 | +* Loading: |
| 178 | + * `.json` files are treated as JSON text files. When importing JSON modules, |
| 179 | + an import type attribute is required (e.g. |
| 180 | + `import json from './data.json' with { type: 'json' }`). |
| 181 | + * `.node` files are interpreted as compiled addon modules loaded with |
| 182 | + `process.dlopen()`, if [`--experimental-addon-modules`][] is enabled. |
| 183 | + * `.ts`, `.mts` and `.cts` files are treated as [TypeScript][] text files. |
| 184 | + * It accepts only `.js`, `.mjs`, and `.cjs` extensions for JavaScript text |
| 185 | + files. |
| 186 | + * `.wasm` files are treated as [WebAssembly modules][]. |
| 187 | + * Any other file extensions will result in a [`ERR_UNKNOWN_FILE_EXTENSION`][] error. |
| 188 | + Additional file extensions can be facilitated via [customization hooks][]. |
| 189 | + * `import`/`import()` can be used to load JavaScript [CommonJS modules][commonjs]. |
| 190 | + Such modules are passed through the `cjs-module-lexer` to try to identify named |
| 191 | + exports, which are available if they can be determined through static analysis. |
| 192 | + |
| 193 | +Regardless of how a module is requested, the resolution and loading process can be customized |
| 194 | +using [customization hooks][]. |
185 | 195 |
|
186 | 196 | ### `package.json` and file extensions |
187 | 197 |
|
@@ -1151,21 +1161,25 @@ This field defines [subpath imports][] for the current package. |
1151 | 1161 | [Node.js documentation for this section]: https://github.com/nodejs/node/blob/HEAD/doc/api/packages.md#conditions-definitions |
1152 | 1162 | [Runtime Keys]: https://runtime-keys.proposal.wintercg.org/ |
1153 | 1163 | [Syntax detection]: #syntax-detection |
| 1164 | +[TypeScript]: typescript.md |
| 1165 | +[WebAssembly modules]: esm.md#wasm-modules |
1154 | 1166 | [WinterCG]: https://wintercg.org/ |
1155 | 1167 | [`"exports"`]: #exports |
1156 | 1168 | [`"imports"`]: #imports |
1157 | 1169 | [`"main"`]: #main |
1158 | 1170 | [`"name"`]: #name |
1159 | 1171 | [`"type"`]: #type |
1160 | 1172 | [`--conditions` / `-C` flag]: #resolving-user-conditions |
| 1173 | +[`--experimental-addon-modules`]: cli.md#--experimental-addon-modules |
1161 | 1174 | [`--no-addons` flag]: cli.md#--no-addons |
1162 | 1175 | [`ERR_PACKAGE_PATH_NOT_EXPORTED`]: errors.md#err_package_path_not_exported |
| 1176 | +[`ERR_UNKNOWN_FILE_EXTENSION`]: errors.md#err_unknown_file_extension |
1163 | 1177 | [`package.json`]: #nodejs-packagejson-field-definitions |
| 1178 | +[customization hooks]: module.md#customization-hooks |
1164 | 1179 | [entry points]: #package-entry-points |
1165 | 1180 | [folders as modules]: modules.md#folders-as-modules |
1166 | 1181 | [import maps]: https://github.com/WICG/import-maps |
1167 | 1182 | [load ECMAScript modules from CommonJS modules]: modules.md#loading-ecmascript-modules-using-require |
1168 | | -[loader hooks]: esm.md#loaders |
1169 | 1183 | [packages folder mapping]: https://github.com/WICG/import-maps#packages-via-trailing-slashes |
1170 | 1184 | [self-reference]: #self-referencing-a-package-using-its-name |
1171 | 1185 | [subpath exports]: #subpath-exports |
|