- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
Node.js v22.11.0 文档
- Node.js v22.11.0
- 目录
-
导航
- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
- 其他版本
模块:ECMAScript 模块#
¥Modules: ECMAScript modules
¥Stability: 2 - Stable
介绍#
¥Introduction
ECMAScript 模块是 官方标准格式,用于打包 JavaScript 代码以供重用。模块使用各种 import
和 export
语句定义。
¥ECMAScript modules are the official standard format to package JavaScript
code for reuse. Modules are defined using a variety of import
and
export
statements.
以下是 ES 模块导出函数的示例:
¥The following example of an ES module exports a function:
// addTwo.mjs
function addTwo(num) {
return num + 2;
}
export { addTwo };
以下是 ES 模块从 addTwo.mjs
导入函数的示例:
¥The following example of an ES module imports the function from addTwo.mjs
:
// app.mjs
import { addTwo } from './addTwo.mjs';
// Prints: 6
console.log(addTwo(4));
Node.js 完全支持当前指定的 ECMAScript 模块,并提供它们与其原始模块格式 CommonJS 之间的互操作性。
¥Node.js fully supports ECMAScript modules as they are currently specified and provides interoperability between them and its original module format, CommonJS.
启用#
¥Enabling
Node.js 有两个模块系统:CommonJS 模块和 ECMAScript 模块。
¥Node.js has two module systems: CommonJS modules and ECMAScript modules.
作者可以通过 .mjs
文件扩展名、值为 "module"
的 package.json
"type"
字段、值为 "module"
的 --input-type
标志或值为 "module"
的 --experimental-default-type
标志,告诉 Node.js 将 JavaScript 解释为 ES 模块。这些是打算作为 ES 模块运行的代码的显式标记。
¥Authors can tell Node.js to interpret JavaScript as an ES module via the .mjs
file extension, the package.json
"type"
field with a value "module"
,
the --input-type
flag with a value of "module"
, or the
--experimental-default-type
flag with a value of "module"
. These are
explicit markers of code being intended to run as an ES module.
相反,作者可以通过 .cjs
文件扩展名、值为 "commonjs"
的 package.json
"type"
字段、值为 "commonjs"
的 --input-type
标志或值为 "commonjs"
的 --experimental-default-type
标志,告诉 Node.js 将 JavaScript 解释为 CommonJS。
¥Inversely, authors can tell Node.js to interpret JavaScript as CommonJS via the
.cjs
file extension, the package.json
"type"
field with a value
"commonjs"
, the --input-type
flag with a value of "commonjs"
, or the
--experimental-default-type
flag with a value of "commonjs"
.
当代码缺少任一模块系统的显式标记时,Node.js 将检查模块的源代码以查找 ES 模块语法。如果找到这样的语法,Node.js 会将代码作为 ES 模块运行;否则它将作为 CommonJS 运行该模块。有关详细信息,请参阅 确定模块系统。
¥When code lacks explicit markers for either module system, Node.js will inspect the source code of a module to look for ES module syntax. If such syntax is found, Node.js will run the code as an ES module; otherwise it will run the module as CommonJS. See Determining module system for more details.
包#
¥Packages
此部分已移至 模块:包。
¥This section was moved to Modules: Packages.
import
说明符#
¥import
Specifiers
术语#
¥Terminology
import
语句的说明符是 from
关键字之后的字符串,例如 import { sep } from 'node:path'
中的 'node:path'
。说明符也用于 export from
语句,并作为 import()
表达式的参数。
¥The specifier of an import
statement is the string after the from
keyword,
e.g. 'node:path'
in import { sep } from 'node:path'
. Specifiers are also
used in export from
statements, and as the argument to an import()
expression.
有三种类型的说明符:
¥There are three types of specifiers:
-
相对说明符,如
'./startup.js'
或'../config.mjs'
。它们指的是相对于导入文件位置的路径。这些文件扩展名始终是必需的。¥Relative specifiers like
'./startup.js'
or'../config.mjs'
. They refer to a path relative to the location of the importing file. The file extension is always necessary for these. -
纯说明符,如
'some-package'
或'some-package/shuffle'
。它们可以通过包名称来引用包的主要入口点,或者根据示例分别以包名称为前缀的包中的特定功能模块。只有没有"exports"
字段的包才需要包含文件扩展名。¥Bare specifiers like
'some-package'
or'some-package/shuffle'
. They can refer to the main entry point of a package by the package name, or a specific feature module within a package prefixed by the package name as per the examples respectively. Including the file extension is only necessary for packages without an"exports"
field. -
绝对说明符,如
'file:///opt/nodejs/config.js'
。它们直接且明确地引用完整的路径。¥Absolute specifiers like
'file:///opt/nodejs/config.js'
. They refer directly and explicitly to a full path.
裸说明符解析由 Node.js 模块解析和加载算法 处理。所有其他说明符解析始终仅使用标准的相对 URL 解析语义进行解析。
¥Bare specifier resolutions are handled by the Node.js module resolution and loading algorithm. All other specifier resolutions are always only resolved with the standard relative URL resolution semantics.
就像在 CommonJS 中一样,包中的模块文件可以通过在包名称后附加路径来访问,除非包的 package.json
包含 "exports"
字段,在这种情况下,包中的文件只能通过 "exports"
中定义的路径访问。
¥Like in CommonJS, module files within packages can be accessed by appending a
path to the package name unless the package's package.json
contains an
"exports"
field, in which case files within packages can only be accessed
via the paths defined in "exports"
.
有关适用于 Node.js 模块解析中的裸说明符的这些包解析规则的详细信息,请参阅 包文档。
¥For details on these package resolution rules that apply to bare specifiers in the Node.js module resolution, see the packages documentation.
强制文件扩展名#
¥Mandatory file extensions
当使用 import
关键字解析相对或绝对的说明符时,必须提供文件扩展名。还必须完全指定目录索引(例如 './startup/index.js'
)。
¥A file extension must be provided when using the import
keyword to resolve
relative or absolute specifiers. Directory indexes (e.g. './startup/index.js'
)
must also be fully specified.
此行为与 import
在浏览器环境中的行为方式相匹配,假设服务器是典型配置的。
¥This behavior matches how import
behaves in browser environments, assuming a
typically configured server.
URL#
ES 模块被解析并缓存为 URL。这意味着特殊字符必须是 percent-encoded,例如 #
必须是 %23
,?
必须是 %3F
。
¥ES modules are resolved and cached as URLs. This means that special characters
must be percent-encoded, such as #
with %23
and ?
with %3F
.
支持 file:
、node:
和 data:
URL 协议。除非使用 自定义 HTTPS 加载器,否则 Node.js 本身不支持像 'https://example.com/app.js'
这样的说明符。
¥file:
, node:
, and data:
URL schemes are supported. A specifier like
'https://example.com/app.js'
is not supported natively in Node.js unless using
a custom HTTPS loader.
file:
URL#
如果用于解析模块的 import
说明符具有不同的查询或片段,则会多次加载模块。
¥Modules are loaded multiple times if the import
specifier used to resolve
them has a different query or fragment.
import './foo.mjs?query=1'; // loads ./foo.mjs with query of "?query=1"
import './foo.mjs?query=2'; // loads ./foo.mjs with query of "?query=2"
可以通过 /
、//
、或 file:///
引用卷根。考虑到 URL 和路径解析的差异(比如百分比编码细节),建议导入路径时使用 url.pathToFileURL。
¥The volume root may be referenced via /
, //
, or file:///
. Given the
differences between URL and path resolution (such as percent encoding
details), it is recommended to use url.pathToFileURL when importing a path.
data:
导入#
¥data:
imports
data:
URL 支持使用以下 MIME 类型导入:
¥data:
URLs are supported for importing with the following MIME types:
-
text/javascript
用于 ES 模块¥
text/javascript
for ES modules -
application/json
用于 JSON¥
application/json
for JSON -
application/wasm
用于 Wasm¥
application/wasm
for Wasm
import 'data:text/javascript,console.log("hello!");';
import _ from 'data:application/json,"world!"' with { type: 'json' };
data:
URL 仅解析内置模块的 裸说明符 和 绝对说明符。解析 相对说明符 不起作用,因为 data:
不是 特别计划。例如,尝试从 data:text/javascript,import "./foo";
加载 ./foo
无法解析,因为 data:
URL 没有相对解析的概念。
¥data:
URLs only resolve bare specifiers for builtin modules
and absolute specifiers. Resolving
relative specifiers does not work because data:
is not a
special scheme. For example, attempting to load ./foo
from data:text/javascript,import "./foo";
fails to resolve because there
is no concept of relative resolution for data:
URLs.
node:
导入#
¥node:
imports
支持 node:
URL 作为加载 Node.js 内置模块的替代方法。此 URL 协议允许有效的绝对的 URL 字符串引用内置模块。
¥node:
URLs are supported as an alternative means to load Node.js builtin
modules. This URL scheme allows for builtin modules to be referenced by valid
absolute URL strings.
import fs from 'node:fs/promises';
导入属性#
¥Import attributes
¥Stability: 1.1 - Active development
此功能以前被命名为 "导入断言",并使用
assert
关键字而不是with
。代码中先前assert
关键字的任何使用都应更新为使用with
。¥This feature was previously named "Import assertions", and using the
assert
keyword instead ofwith
. Any uses in code of the priorassert
keyword should be updated to usewith
instead.
导入属性提案 为模块导入语句添加了内联语法,以便在模块说明符旁边传递更多信息。
¥The Import Attributes proposal adds an inline syntax for module import statements to pass on more information alongside the module specifier.
import fooData from './foo.json' with { type: 'json' };
const { default: barData } =
await import('./bar.json', { with: { type: 'json' } });
Node.js 支持以下 type
值,该属性是必需的:
¥Node.js supports the following type
values, for which the attribute is
mandatory:
属性 type | 需要用于 |
---|---|
'json' | JSON 模块 |
内置模块#
¥Built-in modules
内置模块 提供其公共 API 的命名导出。还提供了默认导出,其是 CommonJS 导出的值。默认导出可用于修改命名导出等。内置模块的命名导出只能通过调用 module.syncBuiltinESMExports()
来更新。
¥Built-in modules provide named exports of their public API. A
default export is also provided which is the value of the CommonJS exports.
The default export can be used for, among other things, modifying the named
exports. Named exports of built-in modules are updated only by calling
module.syncBuiltinESMExports()
.
import EventEmitter from 'node:events';
const e = new EventEmitter();
import { readFile } from 'node:fs';
readFile('./foo.txt', (err, source) => {
if (err) {
console.error(err);
} else {
console.log(source);
}
});
import fs, { readFileSync } from 'node:fs';
import { syncBuiltinESMExports } from 'node:module';
import { Buffer } from 'node:buffer';
fs.readFileSync = () => Buffer.from('Hello, ESM');
syncBuiltinESMExports();
fs.readFileSync === readFileSync;
import()
表达式#
¥import()
expressions
CommonJS 和 ES 模块都支持 动态 import()
。在 CommonJS 模块中它可以用来加载 ES 模块。
¥Dynamic import()
is supported in both CommonJS and ES modules. In CommonJS
modules it can be used to load ES modules.
import.meta
#
import.meta
元属性是包含以下属性的 Object
。
¥The import.meta
meta property is an Object
that contains the following
properties.
import.meta.dirname
#
¥Stability: 1.2 - Release candidate
-
<string> 当前模块的目录名。这与
import.meta.filename
的path.dirname()
相同。¥<string> The directory name of the current module. This is the same as the
path.dirname()
of theimport.meta.filename
.
警告:仅存在于
file:
模块上。¥Caveat: only present on
file:
modules.
import.meta.filename
#
¥Stability: 1.2 - Release candidate
-
<string> 当前模块的完整绝对路径和文件名,带有已解析的符号链接。
¥<string> The full absolute path and filename of the current module, with symlinks resolved.
-
这与
import.meta.url
的url.fileURLToPath()
相同。¥This is the same as the
url.fileURLToPath()
of theimport.meta.url
.
警告 只有本地模块支持此属性。不使用
file:
协议的模块将不会提供它。¥only local modules support this property. Modules not using the
file:
protocol will not provide it.
import.meta.url
#
这与提供当前模块文件 URL 的浏览器中的定义完全相同。
¥This is defined exactly the same as it is in browsers providing the URL of the current module file.
这可以启用有用的模式,例如相对文件加载
¥This enables useful patterns such as relative file loading:
import { readFileSync } from 'node:fs';
const buffer = readFileSync(new URL('./data.proto', import.meta.url));
import.meta.resolve(specifier)
#
¥Stability: 1.2 - Release candidate
-
specifier
<string> 相对于当前模块解析的模块说明符。¥
specifier
<string> The module specifier to resolve relative to the current module. -
返回:<string> 说明符将解析为的绝对 URL 字符串。
¥Returns: <string> The absolute URL string that the specifier would resolve to.
import.meta.resolve
是一个模块相对解析函数,作用域为每个模块,返回 URL 字符串。
¥import.meta.resolve
is a module-relative resolution function scoped to
each module, returning the URL string.
const dependencyAsset = import.meta.resolve('component-lib/asset.css');
// file:///app/node_modules/component-lib/asset.css
import.meta.resolve('./dep.js');
// file:///app/dep.js
支持 Node.js 模块解析的所有功能。依赖解析受包内允许的导出解析的约束。
¥All features of the Node.js module resolution are supported. Dependency resolutions are subject to the permitted exports resolutions within the package.
注意事项:
¥Caveats:
-
这可能会导致同步文件系统操作,从而对性能产生类似于
require.resolve
的影响。¥This can result in synchronous file-system operations, which can impact performance similarly to
require.resolve
. -
此功能在自定义加载程序中不可用(这会造成死锁)。
¥This feature is not available within custom loaders (it would create a deadlock).
非标准 API:
¥Non-standard API:
当使用 --experimental-import-meta-resolve
标志时,该函数接受第二个参数:
¥When using the --experimental-import-meta-resolve
flag, that function accepts
a second argument:
与 CommonJS 的互操作性#
¥Interoperability with CommonJS
import
语句#
¥import
statements
import
语句可以引用 ES 模块或 CommonJS 模块。import
语句只允许在 ES 模块中使用,但 CommonJS 支持动态 import()
表达式来加载 ES 模块。
¥An import
statement can reference an ES module or a CommonJS module.
import
statements are permitted only in ES modules, but dynamic import()
expressions are supported in CommonJS for loading ES modules.
导入 CommonJS 模块 时,module.exports
对象作为默认导出提供。命名导出可能可用,由静态分析提供,以方便更好的生态系统兼容性。
¥When importing CommonJS modules, the
module.exports
object is provided as the default export. Named exports may be
available, provided by static analysis as a convenience for better ecosystem
compatibility.
require
#
CommonJS 模块 require
目前仅支持在启用 --experimental-require-module
时加载同步 ES 模块。
¥The CommonJS module require
currently only supports loading synchronous ES
modules when --experimental-require-module
is enabled.
详见 使用 require()
加载 ECMAScript 模块。
¥See Loading ECMAScript modules using require()
for details.
CommonJS 命名空间#
¥CommonJS Namespaces
CommonJS 模块由可以是任何类型的 module.exports
对象组成。
¥CommonJS modules consist of a module.exports
object which can be of any type.
当导入 CommonJS 模块时,可以使用 ES 模块默认导入或其对应的语法糖可靠地导入:
¥When importing a CommonJS module, it can be reliably imported using the ES module default import or its corresponding sugar syntax:
import { default as cjs } from 'cjs';
// The following import statement is "syntax sugar" (equivalent but sweeter)
// for `{ default as cjsSugar }` in the above import statement:
import cjsSugar from 'cjs';
console.log(cjs);
console.log(cjs === cjsSugar);
// Prints:
// <module.exports>
// true
CommonJS 模块的 ECMAScript 模块命名空间表示始终是使用 default
导出键指向 CommonJS module.exports
值的命名空间。
¥The ECMAScript Module Namespace representation of a CommonJS module is always
a namespace with a default
export key pointing to the CommonJS
module.exports
value.
当使用 import * as m from 'cjs'
或动态导入时,可以直接观察到此模块命名空间外来对象:
¥This Module Namespace Exotic Object can be directly observed either when using
import * as m from 'cjs'
or a dynamic import:
import * as m from 'cjs';
console.log(m);
console.log(m === await import('cjs'));
// Prints:
// [Module] { default: <module.exports> }
// true
为了更好地兼容 JS 生态系统中的现有用法,Node.js 还尝试确定每个导入的 CommonJS 模块的 CommonJS 命名导出,以使用静态分析过程将它们作为单独的 ES 模块导出提供。
¥For better compatibility with existing usage in the JS ecosystem, Node.js in addition attempts to determine the CommonJS named exports of every imported CommonJS module to provide them as separate ES module exports using a static analysis process.
例如,考虑编写的 CommonJS 模块:
¥For example, consider a CommonJS module written:
// cjs.cjs
exports.name = 'exported';
前面的模块支持 ES 模块中的命名导入:
¥The preceding module supports named imports in ES modules:
import { name } from './cjs.cjs';
console.log(name);
// Prints: 'exported'
import cjs from './cjs.cjs';
console.log(cjs);
// Prints: { name: 'exported' }
import * as m from './cjs.cjs';
console.log(m);
// Prints: [Module] { default: { name: 'exported' }, name: 'exported' }
从上一个记录模块命名空间外来对象的示例中可以看出,name
导出是从 module.exports
对象复制出来的,并在导入模块时直接设置在 ES 模块命名空间上。
¥As can be seen from the last example of the Module Namespace Exotic Object being
logged, the name
export is copied off of the module.exports
object and set
directly on the ES module namespace when the module is imported.
未检测到这些命名导出的实时绑定更新或添加到 module.exports
的新导出。
¥Live binding updates or new exports added to module.exports
are not detected
for these named exports.
命名导出的检测基于通用语法模式,但并不总是正确地检测命名导出。在这些情况下,使用上述默认导入形式可能是更好的选择。
¥The detection of named exports is based on common syntax patterns but does not always correctly detect named exports. In these cases, using the default import form described above can be a better option.
命名导出检测涵盖了许多常见的导出模式、再导出模式、以及构建工具和转译器输出。有关实现的确切语义,请参阅 cjs-module-lexer。
¥Named exports detection covers many common export patterns, reexport patterns and build tool and transpiler outputs. See cjs-module-lexer for the exact semantics implemented.
ES 模块和 CommonJS 的区别#
¥Differences between ES modules and CommonJS
无 require
、exports
或 module.exports
#
¥No require
, exports
, or module.exports
在大多数情况下,可以使用 ES 模块 import
加载 CommonJS 模块。
¥In most cases, the ES module import
can be used to load CommonJS modules.
如果需要,可以使用 module.createRequire()
在 ES 模块中构造 require
函数。
¥If needed, a require
function can be constructed within an ES module using
module.createRequire()
.
无 __filename
或 __dirname
#
¥No __filename
or __dirname
这些 CommonJS 变量在 ES 模块中不可用。
¥These CommonJS variables are not available in ES modules.
__filename
和 __dirname
用例可以通过 import.meta.filename
和 import.meta.dirname
复制。
¥__filename
and __dirname
use cases can be replicated via
import.meta.filename
and import.meta.dirname
.
没有插件加载#
¥No Addon Loading
插件 当前不支持 ES 模块导入。
¥Addons are not currently supported with ES module imports.
它们可以改为加载 module.createRequire()
或 process.dlopen
。
¥They can instead be loaded with module.createRequire()
or
process.dlopen
.
没有 require.resolve
#
¥No require.resolve
相对解析可以通过 new URL('./local', import.meta.url)
处理。
¥Relative resolution can be handled via new URL('./local', import.meta.url)
.
对于完整的 require.resolve
替代品,有 import.meta.resolve API。
¥For a complete require.resolve
replacement, there is the
import.meta.resolve API.
也可以使用 module.createRequire()
。
¥Alternatively module.createRequire()
can be used.
没有 NODE_PATH
#
¥No NODE_PATH
NODE_PATH
不是解析 import
说明符的一部分。如果需要这种行为,则使用符号链接。
¥NODE_PATH
is not part of resolving import
specifiers. Please use symlinks
if this behavior is desired.
没有 require.extensions
#
¥No require.extensions
require.extensions
没有被 import
使用。模块定制钩子可以提供替代品。
¥require.extensions
is not used by import
. Module customization hooks can
provide a replacement.
没有 require.cache
#
¥No require.cache
require.cache
没有被 import
使用,因为 ES 模块加载器有自己独立的缓存。
¥require.cache
is not used by import
as the ES module loader has its own
separate cache.
JSON 模块#
¥JSON modules
¥Stability: 1 - Experimental
import
可以引用 JSON 文件:
¥JSON files can be referenced by import
:
import packageConfig from './package.json' with { type: 'json' };
with { type: 'json' }
语法是强制性的;见 导入属性。
¥The with { type: 'json' }
syntax is mandatory; see Import Attributes.
导入的 JSON 只暴露一个 default
导出。不支持命名导出。在 CommonJS 缓存中创建缓存条目,以避免重复。如果 JSON 模块已经从同一路径导入,则在 CommonJS 中返回相同的对象。
¥The imported JSON only exposes a default
export. There is no support for named
exports. A cache entry is created in the CommonJS cache to avoid duplication.
The same object is returned in CommonJS if the JSON module has already been
imported from the same path.
Wasm 模块#
¥Wasm modules
¥Stability: 1 - Experimental
在 --experimental-wasm-modules
标志下支持导入 WebAssembly 模块,允许将任何 .wasm
文件作为普通模块导入,同时也支持它们的模块导入。
¥Importing WebAssembly modules is supported under the
--experimental-wasm-modules
flag, allowing any .wasm
files to be
imported as normal modules while also supporting their module imports.
这种整合是符合 WebAssembly 的 ES 模块集成提案 的。
¥This integration is in line with the ES Module Integration Proposal for WebAssembly.
例如,index.mjs
包含:
¥For example, an index.mjs
containing:
import * as M from './module.wasm';
console.log(M);
在以下条件下执行:
¥executed under:
node --experimental-wasm-modules index.mjs
将为 module.wasm
的实例化提供导出接口。
¥would provide the exports interface for the instantiation of module.wasm
.
顶层 await
#
¥Top-level await
await
关键字可以用在 ECMAScript 模块的顶层主体中。
¥The await
keyword may be used in the top level body of an ECMAScript module.
假设 a.mjs
具有
¥Assuming an a.mjs
with
export const five = await Promise.resolve(5);
并且 b.mjs
具有
¥And a b.mjs
with
import { five } from './a.mjs';
console.log(five); // Logs `5`
node b.mjs # works
如果顶层 await
表达式永远无法解析,则 node
进程将退出并返回 13
状态码。
¥If a top level await
expression never resolves, the node
process will exit
with a 13
status code.
import { spawn } from 'node:child_process';
import { execPath } from 'node:process';
spawn(execPath, [
'--input-type=module',
'--eval',
// Never-resolving Promise:
'await new Promise(() => {})',
]).once('exit', (code) => {
console.log(code); // Logs `13`
});
加载器#
¥Loaders
以前的 Loaders 文档现在位于 模块:定制钩子。
¥The former Loaders documentation is now at Modules: Customization hooks.
解析和加载算法#
¥Resolution and loading algorithm
特性#
¥Features
默认解析器具有以下属性:
¥The default resolver has the following properties:
-
ES 模块使用的基于 FileURL 的解析
¥FileURL-based resolution as is used by ES modules
-
相对和绝对的网址解析
¥Relative and absolute URL resolution
-
没有默认的扩展名
¥No default extensions
-
没有主文件夹
¥No folder mains
-
通过 node_modules 进行裸说明符包解析查找
¥Bare specifier package resolution lookup through node_modules
-
不会在未知扩展或协议上失败
¥Does not fail on unknown extensions or protocols
-
可以选择向加载阶段提供格式提示
¥Can optionally provide a hint of the format to the loading phase
默认加载器具有以下属性
¥The default loader has the following properties
-
支持通过
node:
URL 加载内置模块¥Support for builtin module loading via
node:
URLs -
支持通过
data:
URL 加载 "inline" 模块¥Support for "inline" module loading via
data:
URLs -
支持
file:
模块加载¥Support for
file:
module loading -
在任何其他 URL 协议上失败
¥Fails on any other URL protocol
-
加载
file:
的未知扩展失败(仅支持.cjs
、.js
和.mjs
)¥Fails on unknown extensions for
file:
loading (supports only.cjs
,.js
, and.mjs
)
解析算法#
¥Resolution algorithm
加载 ES 模块说明符的算法通过下面的 ESM_RESOLVE 方法给出。它返回相对于 parentURL 的模块说明符的解析 URL。
¥The algorithm to load an ES module specifier is given through the ESM_RESOLVE method below. It returns the resolved URL for a module specifier relative to a parentURL.
解析算法确定模块加载的完整解析 URL 及其建议的模块格式。解析算法不确定是否可以加载已解析的 URL 协议,或者是否允许文件扩展名,而是由 Node.js 在加载阶段应用这些验证(例如,如果要求加载具有非 file:
、data:
或 node:
协议的 URL。
¥The resolution algorithm determines the full resolved URL for a module
load, along with its suggested module format. The resolution algorithm
does not determine whether the resolved URL protocol can be loaded,
or whether the file extensions are permitted, instead these validations
are applied by Node.js during the load phase
(for example, if it was asked to load a URL that has a protocol that is
not file:
, data:
or node:
.
该算法还尝试根据扩展名确定文件的格式(参见下面的 ESM_FILE_FORMAT
算法)。如果它不识别文件扩展名(例如,如果它不是 .mjs
、.cjs
或 .json
),则返回 undefined
格式,这将在加载阶段抛出。
¥The algorithm also tries to determine the format of the file based
on the extension (see ESM_FILE_FORMAT
algorithm below). If it does
not recognize the file extension (eg if it is not .mjs
, .cjs
, or
.json
), then a format of undefined
is returned,
which will throw during the load phase.
ESM_FILE_FORMAT 提供了确定已解析 URL 的模块格式的算法,该算法返回任何文件的唯一模块格式。"module" 格式为 ECMAScript 模块返回,而 "commonjs" 格式用于指示通过旧版 CommonJS 加载器加载。可以在未来的更新中扩展其他格式,例如 "addon"。
¥The algorithm to determine the module format of a resolved URL is provided by ESM_FILE_FORMAT, which returns the unique module format for any file. The "module" format is returned for an ECMAScript Module, while the "commonjs" format is used to indicate loading through the legacy CommonJS loader. Additional formats such as "addon" can be extended in future updates.
在以下算法中,除非另有说明,否则所有子程序错误都将作为这些顶层程序的错误传播。
¥In the following algorithms, all subroutine errors are propagated as errors of these top-level routines unless stated otherwise.
defaultConditions 是条件环境名称数组,["node", "import"]
。
¥defaultConditions is the conditional environment name array,
["node", "import"]
.
解析器可能会抛出以下错误:
¥The resolver can throw the following errors:
-
无效的模块说明符:模块说明符是无效的 URL、包名称或包的子路径说明符。
¥Invalid Module Specifier: Module specifier is an invalid URL, package name or package subpath specifier.
-
无效的包配置:package.json 配置无效或包含无效配置。
¥Invalid Package Configuration: package.json configuration is invalid or contains an invalid configuration.
-
无效的包目标:包导出或导入为包定义了一个目标模块,该模块是无效类型或字符串目标。
¥Invalid Package Target: Package exports or imports define a target module for the package that is an invalid type or string target.
-
未导出的包路径:包导出不为给定模块定义或允许包中的目标子路径。
¥Package Path Not Exported: Package exports do not define or permit a target subpath in the package for the given module.
-
包导入未定义:包导入不定义说明符。
¥Package Import Not Defined: Package imports do not define the specifier.
-
未找到模块:请求的包或模块不存在。
¥Module Not Found: The package or module requested does not exist.
-
不支持的目录导入:解析的路径对应于一个目录,该目录不是模块导入的受支持目标。
¥Unsupported Directory Import: The resolved path corresponds to a directory, which is not a supported target for module imports.
解析算法规范#
¥Resolution Algorithm Specification
ESM_RESOLVE(specifier, parentURL)
让 resolved 为未定义。
¥Let resolved be undefined.
如果说明符是有效的 URL,则
¥If specifier is a valid URL, then
将 resolved 设置为将说明符解析和重新序列化为 URL 的结果。
¥Set resolved to the result of parsing and reserializing specifier as a URL.
否则,如果说明符以 "/"、"./" 或 "../" 开头,则
¥Otherwise, if specifier starts with "/", "./", or "../", then
将 resolved 设置为说明符相对于 parentURL 的 URL 解析。
¥Set resolved to the URL resolution of specifier relative to parentURL.
否则,如果说明符以 "" 开头,则
¥Otherwise, if specifier starts with "#", then
将已解析设置为 PACKAGE_IMPORTS_RESOLVE(specifier,parentURL,defaultConditions) 的结果。
¥Set resolved to the result of PACKAGE_IMPORTS_RESOLVE(specifier, parentURL, defaultConditions).
否则,
¥Otherwise,
注意:说明符现在是一个裸说明符。
¥Note: specifier is now a bare specifier.
设置解析 PACKAGE_RESOLVE(specifier,parentURL) 的结果。
¥Set resolved the result of PACKAGE_RESOLVE(specifier, parentURL).
让格式未定义。
¥Let format be undefined.
如果解析的是 "file:" URL,则
¥If resolved is a "file:" URL, then
如果已解析包含 "/" 或 ""(分别为 "%2F" 和 "%5C")的任何百分比编码,则
¥If resolved contains any percent encodings of "/" or "" ("%2F" and "%5C" respectively), then
抛出无效的模块说明符错误。
¥Throw an Invalid Module Specifier error.
如果解析的文件是一个目录,那么
¥If the file at resolved is a directory, then
引发不支持的目录导入错误。
¥Throw an Unsupported Directory Import error.
如果已解析的文件不存在,则
¥If the file at resolved does not exist, then
抛出模块未找到错误。
¥Throw a Module Not Found error.
设置 resolved 为 resolved 的真实路径,保持相同的 URL querystring 和 fragment 组件。
¥Set resolved to the real path of resolved, maintaining the same URL querystring and fragment components.
将格式设置为 ESM_FILE_FORMAT(resolved) 的结果。
¥Set format to the result of ESM_FILE_FORMAT(resolved).
否则,
¥Otherwise,
设置格式与解析的 URL 关联的内容类型的模块格式。
¥Set format the module format of the content type associated with the URL resolved.
返回格式并解析到加载阶段
¥Return format and resolved to the loading phase
PACKAGE_RESOLVE(packageSpecifier, parentURL)
让 packageName 未定义。
¥Let packageName be undefined.
如果 packageSpecifier 是空字符串,则
¥If packageSpecifier is an empty string, then
抛出无效的模块说明符错误。
¥Throw an Invalid Module Specifier error.
如果 packageSpecifier 是 Node.js 内置模块名称,则
¥If packageSpecifier is a Node.js builtin module name, then
返回与 packageSpecifier 连接的字符串 "node:"。
¥Return the string "node:" concatenated with packageSpecifier.
如果 packageSpecifier 不以 "@" 开头,则
¥If packageSpecifier does not start with "@", then
将 packageName 设置为 packageSpecifier 的子字符串,直到第一个 "/" 分隔符或字符串的结尾。
¥Set packageName to the substring of packageSpecifier until the first "/" separator or the end of the string.
否则,
¥Otherwise,
如果 packageSpecifier 不包含 "/" 分隔符,则
¥If packageSpecifier does not contain a "/" separator, then
抛出无效的模块说明符错误。
¥Throw an Invalid Module Specifier error.
将 packageName 设置为 packageSpecifier 的子字符串,直到第二个 "/" 分隔符或字符串的末尾。
¥Set packageName to the substring of packageSpecifier until the second "/" separator or the end of the string.
如果 packageName 以 "." 开头或包含 "" 或 "%",则
¥If packageName starts with "." or contains "" or "%", then
抛出无效的模块说明符错误。
¥Throw an Invalid Module Specifier error.
让 packageSubpath "." 与 packageSpecifier 的子字符串从 packageName 长度的位置连接起来。
¥Let packageSubpath be "." concatenated with the substring of packageSpecifier from the position at the length of packageName.
如果 packageSubpath 以 "/" 结尾,则
¥If packageSubpath ends in "/", then
抛出无效的模块说明符错误。
¥Throw an Invalid Module Specifier error.
令 selfUrl 为 PACKAGE_SELF_RESOLVE(packageName, packageSubpath, ParentURL) 的结果。
¥Let selfUrl be the result of PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL).
如果 selfUrl 不是未定义,则返回 selfUrl。
¥If selfUrl is not undefined, return selfUrl.
虽然 parentURL 不是文件系统根目录,
¥While parentURL is not the file system root,
令 packageURL 为 "node_modules/" 的 URL 解析与 packageSpecifier 连接,相对于 parentURL。
¥Let packageURL be the URL resolution of "node_modules/" concatenated with packageSpecifier, relative to parentURL.
将 parentURL 设置为 parentURL 的父文件夹 URL。
¥Set parentURL to the parent folder URL of parentURL.
如果 packageURL 处的文件夹不存在,则
¥If the folder at packageURL does not exist, then
继续下一个循环迭代。
¥Continue the next loop iteration.
令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。
¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).
如果 pjson 不为 null 并且 pjson.exports 不为 null 或未定义,则
¥If pjson is not null and pjson.exports is not null or undefined, then
返回 PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions) 的结果。
¥Return the result of PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions).
否则,如果 packageSubpath 等于 ".",则
¥Otherwise, if packageSubpath is equal to ".", then
如果 pjson.main 是一个字符串,那么
¥If pjson.main is a string, then
返回 packageURL 中 main 的 URL 解析。
¥Return the URL resolution of main in packageURL.
否则,
¥Otherwise,
返回 packageURL 中 packageSubpath 的 URL 解析。
¥Return the URL resolution of packageSubpath in packageURL.
抛出模块未找到错误。
¥Throw a Module Not Found error.
PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL)
令 packageURL 为 LOOKUP_PACKAGE_SCOPE(parentURL) 的结果。
¥Let packageURL be the result of LOOKUP_PACKAGE_SCOPE(parentURL).
如果 packageURL 为 null,则
¥If packageURL is null, then
返回未定义。
¥Return undefined.
令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。
¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).
如果 pjson 为 null 或者 pjson.exports 为 null 或未定义,则
¥If pjson is null or if pjson.exports is null or undefined, then
返回未定义。
¥Return undefined.
如果 pjson.name 等于 packageName,则
¥If pjson.name is equal to packageName, then
返回 PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions) 的结果。
¥Return the result of PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions).
否则,返回未定义。
¥Otherwise, return undefined.
PACKAGE_EXPORTS_RESOLVE(packageURL, subpath, exports, conditions)
如果 exports 是一个对象,其键值以 "." 开头,键值不以 "." 开头,则抛出无效包配置错误。
¥If exports is an Object with both a key starting with "." and a key not starting with ".", throw an Invalid Package Configuration error.
如果子路径等于 ".",则
¥If subpath is equal to ".", then
让 mainExport 未定义。
¥Let mainExport be undefined.
如果导出是字符串或数组,或者不包含以 "." 开头的键的对象,则
¥If exports is a String or Array, or an Object containing no keys starting with ".", then
将 mainExport 设置为导出。
¥Set mainExport to exports.
否则,如果导出是包含 "." 属性的对象,则
¥Otherwise if exports is an Object containing a "." property, then
将 mainExport 设置为导出 ["."]。
¥Set mainExport to exports["."].
如果 mainExport 不是未定义的,那么
¥If mainExport is not undefined, then
令已解析为 PACKAGE_TARGET_RESOLVE(packageURL, mainExport, null, false, criteria) 的结果。
¥Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, mainExport, null, false, conditions).
如果 resolved 不为 null 或未定义,则返回 resolved。
¥If resolved is not null or undefined, return resolved.
否则,如果 exports 是一个 Object 并且 exports 的所有 key 都以 "." 开头,那么
¥Otherwise, if exports is an Object and all keys of exports start with ".", then
断言:子路径以 "./" 开头。
¥Assert: subpath begins with "./".
令 resolved 为 PACKAGE_IMPORTS_EXPORTS_RESOLVE(subpath,exports,packageURL,false,conditions)的结果。
¥Let resolved be the result of PACKAGE_IMPORTS_EXPORTS_RESOLVE( subpath, exports, packageURL, false, conditions).
如果 resolved 不为 null 或未定义,则返回 resolved。
¥If resolved is not null or undefined, return resolved.
抛出包路径未导出错误。
¥Throw a Package Path Not Exported error.
PACKAGE_IMPORTS_RESOLVE(specifier, parentURL, conditions)
断言:说明符以 "" 开头。
¥Assert: specifier begins with "#".
如果说明符完全等于 "" 或以 "#/" 开头,则
¥If specifier is exactly equal to "#" or starts with "#/", then
抛出无效的模块说明符错误。
¥Throw an Invalid Module Specifier error.
令 packageURL 为 LOOKUP_PACKAGE_SCOPE(parentURL) 的结果。
¥Let packageURL be the result of LOOKUP_PACKAGE_SCOPE(parentURL).
如果 packageURL 不为 null,则
¥If packageURL is not null, then
令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。
¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).
如果 pjson.imports 是一个非空对象,那么
¥If pjson.imports is a non-null Object, then
令 resolved 为 PACKAGE_IMPORTS_EXPORTS_RESOLVE(specifier, pjson.imports, packageURL, true, Conditions) 的结果。
¥Let resolved be the result of PACKAGE_IMPORTS_EXPORTS_RESOLVE( specifier, pjson.imports, packageURL, true, conditions).
如果 resolved 不为 null 或未定义,则返回 resolved。
¥If resolved is not null or undefined, return resolved.
抛出包导入未定义错误。
¥Throw a Package Import Not Defined error.
PACKAGE_IMPORTS_EXPORTS_RESOLVE(matchKey, matchObj, packageURL, isImports, conditions)
如果 matchKey 是 matchObj 的键并且不包含 "*",则
¥If matchKey is a key of matchObj and does not contain ""*, then
令 target 为 matchObj[matchKey] 的值。
¥Let target be the value of matchObj[matchKey].
返回 PACKAGE_TARGET_RESOLVE(packageURL, target, null, isImports, Conditions) 的结果。
¥Return the result of PACKAGE_TARGET_RESOLVE(packageURL, target, null, isImports, conditions).
令 expansionKeys 为仅包含单个 "*" 的 matchObj 的键列表,由排序函数 PATTERN_KEY_COMPARE 排序,该函数按特异性降序排列。
¥Let expansionKeys be the list of keys of matchObj containing only a single ""*, sorted by the sorting function PATTERN_KEY_COMPARE which orders in descending order of specificity.
对于 expansionKeys 中的每个密钥 expansionKey,执行
¥For each key expansionKey in expansionKeys, do
设 patternBase 是 expansionKey 的子串,但不包括第一个 "*" 字符。
¥Let patternBase be the substring of expansionKey up to but excluding the first ""* character.
如果 matchKey 以 patternBase 开头但不等于 patternBase,则
¥If matchKey starts with but is not equal to patternBase, then
设 patternTrailer 是第一个 "*" 字符后索引中 expansionKey 的子串。
¥Let patternTrailer be the substring of expansionKey from the index after the first ""* character.
如果 patternTrailer 的长度为零,或者 matchKey 以 patternTrailer 结尾并且 matchKey 的长度大于或等于 expandationKey 的长度,则
¥If patternTrailer has zero length, or if matchKey ends with patternTrailer and the length of matchKey is greater than or equal to the length of expansionKey, then
令 target 为 matchObj[expansionKey] 的值。
¥Let target be the value of matchObj[expansionKey].
令 patternMatch 为 matchKey 的子字符串,从 patternBase 长度的索引开始,直到 matchKey 的长度减去 patternTrailer 的长度。
¥Let patternMatch be the substring of matchKey starting at the index of the length of patternBase up to the length of matchKey minus the length of patternTrailer.
返回 PACKAGE_TARGET_RESOLVE(packageURL,target,patternMatch,isImports,conditions)的结果。
¥Return the result of PACKAGE_TARGET_RESOLVE(packageURL, target, patternMatch, isImports, conditions).
返回空值。
¥Return null.
PATTERN_KEY_COMPARE(keyA, keyB)
断言:keyA 仅包含一个 "*"。
¥Assert: keyA contains only a single ""*.
断言:keyB 仅包含一个 "*"。
¥Assert: keyB contains only a single ""*.
让 baseLengthA 成为 keyA 中 "*" 的索引。
¥Let baseLengthA be the index of ""* in keyA.
让 baseLengthB 成为 keyB 中 "*" 的索引。
¥Let baseLengthB be the index of ""* in keyB.
如果 baseLengthA 大于 baseLengthB,则返回 -1。
¥If baseLengthA is greater than baseLengthB, return -1.
如果 baseLengthB 大于 baseLengthA,则返回 1。
¥If baseLengthB is greater than baseLengthA, return 1.
如果 keyA 的长度大于 keyB 的长度,返回-1。
¥If the length of keyA is greater than the length of keyB, return -1.
如果 keyB 的长度大于 keyA 的长度,则返回 1。
¥If the length of keyB is greater than the length of keyA, return 1.
返回 0。
¥Return 0.
PACKAGE_TARGET_RESOLVE(packageURL, target, patternMatch, isImports, conditions)
如果目标是一个字符串,那么
¥If target is a String, then
如果目标不是以 "./" 开头,则
¥If target does not start with "./", then
如果 isImports 为 false,或者目标以 "../" 或 "/" 开头,或者目标是有效的 URL,则
¥If isImports is false, or if target starts with "../" or "/", or if target is a valid URL, then
抛出一个无效的包目标错误。
¥Throw an Invalid Package Target error.
如果 patternMatch 是一个字符串,那么
¥If patternMatch is a String, then
返回 PACKAGE_RESOLVE(目标,其中 "*" 的每个实例都替换为模式匹配,packageURL + "/")。
¥Return PACKAGE_RESOLVE(target with every instance of ""* replaced by patternMatch, packageURL + "/").
返回 PACKAGE_RESOLVE(目标, packageURL + "/")。
¥Return PACKAGE_RESOLVE(target, packageURL + "/").
如果 "/" 或 "" 上的目标拆分在第一个 "." 段之后包含任何 ""、"."、".." 或 "node_modules" 段,不区分大小写并包括百分比编码变体,则抛出无效包目标错误。
¥If target split on "/" or "" contains any "", ".", "..", or "node_modules" segments after the first "." segment, case insensitive and including percent encoded variants, throw an Invalid Package Target error.
令 resolvedTarget 为 packageURL 和 target 串联的 URL 解析。
¥Let resolvedTarget be the URL resolution of the concatenation of packageURL and target.
断言:packageURL 包含在 resolvedTarget 中。
¥Assert: packageURL is contained in resolvedTarget.
如果 patternMatch 为空,那么
¥If patternMatch is null, then
返回已解决的目标。
¥Return resolvedTarget.
如果在 "/" 或 "" 上拆分的 patternMatch 包含任何 ""、"."、".." 或 "node_modules" 段,不区分大小写并包括百分比编码变体,则抛出无效模块说明符错误。
¥If patternMatch split on "/" or "" contains any "", ".", "..", or "node_modules" segments, case insensitive and including percent encoded variants, throw an Invalid Module Specifier error.
返回 resolvedTarget 的 URL 解析,其中 "*" 的每个实例都替换为 patternMatch。
¥Return the URL resolution of resolvedTarget with every instance of ""* replaced with patternMatch.
否则,如果 target 是非空对象,则
¥Otherwise, if target is a non-null Object, then
如果目标包含任何索引属性键(如 ECMA-262 6.1.7 数组索引 中定义),则抛出无效包配置错误。
¥If target contains any index property keys, as defined in ECMA-262 6.1.7 Array Index, throw an Invalid Package Configuration error.
对于目标的每个属性 p,按对象插入顺序为:
¥For each property p of target, in object insertion order as,
如果 p 等于 "default" 或条件包含 p 的条目,则
¥If p equals "default" or conditions contains an entry for p, then
设 targetValue 为 target 中 p 属性的值。
¥Let targetValue be the value of the p property in target.
令 resolved 为 PACKAGE_TARGET_RESOLVE(packageURL, targetValue,patternMatch,isImports,conditions) 的结果。
¥Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, targetValue, patternMatch, isImports, conditions).
如果 resolved 等于 undefined,则继续循环。
¥If resolved is equal to undefined, continue the loop.
返回解决。
¥Return resolved.
返回未定义。
¥Return undefined.
否则,如果 target 是一个数组,那么
¥Otherwise, if target is an Array, then
如果 _target.length 为零,则返回 null。
¥If _target.length is zero, return null.
对于目标中的每个项目 targetValue,执行
¥For each item targetValue in target, do
让 resolved 成为 PACKAGE_TARGET_RESOLVE(packageURL, targetValue,patternMatch,isImports,conditions)的结果,在出现任何 Invalid Package Target 错误时继续循环。
¥Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, targetValue, patternMatch, isImports, conditions), continuing the loop on any Invalid Package Target error.
如果 resolved 未定义,则继续循环。
¥If resolved is undefined, continue the loop.
返回解决。
¥Return resolved.
返回或抛出最后的后备解决方案 null 返回或错误。
¥Return or throw the last fallback resolution null return or error.
否则,如果 target 为 null,则返回 null。
¥Otherwise, if target is null, return null.
否则抛出一个 Invalid Package Target 错误。
¥Otherwise throw an Invalid Package Target error.
ESM_FILE_FORMAT(url)
断言:url 对应于现有文件。
¥Assert: url corresponds to an existing file.
如果 url 以 ".mjs" 结尾,则
¥If url ends in ".mjs", then
返回 "module"。
¥Return "module".
如果 url 以 ".cjs" 结尾,则
¥If url ends in ".cjs", then
返回 "commonjs"。
¥Return "commonjs".
如果 url 以 ".json" 结尾,则
¥If url ends in ".json", then
返回 "json"。
¥Return "json".
如果启用了
--experimental-wasm-modules
并且 url 以 ".wasm" 结尾,则¥If
--experimental-wasm-modules
is enabled and url ends in ".wasm", then
返回 "wasm"。
¥Return "wasm".
令 packageURL 为 LOOKUP_PACKAGE_SCOPE(url) 的结果。
¥Let packageURL be the result of LOOKUP_PACKAGE_SCOPE(url).
令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。
¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).
令 packageType 为空。
¥Let packageType be null.
如果 pjson?.type 是 "module" 或 "commonjs",那么
¥If pjson?.type is "module" or "commonjs", then
将 packageType 设置为 pjson.type。
¥Set packageType to pjson.type.
如果 url 以 ".js" 结尾,则
¥If url ends in ".js", then
如果 packageType 不为 null,则
¥If packageType is not null, then
返回包类型。
¥Return packageType.
如果 DETECT_MODULE_SYNTAX(source) 的结果为真,则
¥If the result of DETECT_MODULE_SYNTAX(source) is true, then
返回 "module"。
¥Return "module".
返回 "commonjs"。
¥Return "commonjs".
如果 url 没有任何扩展名,则
¥If url does not have any extension, then
如果 packageType 为 "module" 并且
--experimental-wasm-modules
已启用,并且 url 处的文件包含 WebAssembly 模块的标头,则¥If packageType is "module" and
--experimental-wasm-modules
is enabled and the file at url contains the header for a WebAssembly module, then
返回 "wasm"。
¥Return "wasm".
如果 packageType 不为 null,则
¥If packageType is not null, then
返回包类型。
¥Return packageType.
如果 DETECT_MODULE_SYNTAX(source) 的结果为真,则
¥If the result of DETECT_MODULE_SYNTAX(source) is true, then
返回 "module"。
¥Return "module".
返回 "commonjs"。
¥Return "commonjs".
返回未定义(将在加载阶段抛出)。
¥Return undefined (will throw during load phase).
LOOKUP_PACKAGE_SCOPE(url)
让 scopeURL 为 url。
¥Let scopeURL be url.
虽然 scopeURL 不是文件系统根目录,
¥While scopeURL is not the file system root,
将 scopeURL 设置为 scopeURL 的父 URL。
¥Set scopeURL to the parent URL of scopeURL.
如果 scopeURL 以 "node_modules" 路径段结束,则返回 null。
¥If scopeURL ends in a "node_modules" path segment, return null.
设 pjsonURL 为 scopeURL 中 "package.json" 的解析。
¥Let pjsonURL be the resolution of "package.json" within scopeURL.
如果 pjsonURL 处的文件存在,则
¥if the file at pjsonURL exists, then
返回范围 URL。
¥Return scopeURL.
返回空值。
¥Return null.
READ_PACKAGE_JSON(packageURL)
设 pjsonURL 为 packageURL 中 "package.json" 的解析。
¥Let pjsonURL be the resolution of "package.json" within packageURL.
如果 pjsonURL 处的文件不存在,则
¥If the file at pjsonURL does not exist, then
返回空值。
¥Return null.
如果 packageURL 处的文件未解析为有效的 JSON,则
¥If the file at packageURL does not parse as valid JSON, then
抛出一个无效的包配置错误。
¥Throw an Invalid Package Configuration error.
在 pjsonURL 返回文件的已解析 JSON 源。
¥Return the parsed JSON source of the file at pjsonURL.
DETECT_MODULE_SYNTAX(source)
将源代码解析为 ECMAScript 模块。
¥Parse source as an ECMAScript module.
如果解析成功,则
¥If the parse is successful, then
如果 source 包含顶层
await
、静态import
或export
语句或import.meta
,则返回 true。¥If source contains top-level
await
, staticimport
orexport
statements, orimport.meta
, return true.如果 source 包含任何 CommonJS 封装器变量(
require
、exports
、module
、__filename
或__dirname
)的顶层词法声明(const
、let
或class
),则返回 true。¥If source contains a top-level lexical declaration (
const
,let
, orclass
) of any of the CommonJS wrapper variables (require
,exports
,module
,__filename
, or__dirname
) then return true.否则返回 false。
¥Else return false.
自定义 ESM 说明符解析算法#
¥Customizing ESM specifier resolution algorithm
模块定制钩子 提供了一种用于自定义 ESM 说明符解析算法的机制。为 ESM 说明符提供 CommonJS 样式解析的一个示例是 commonjs-extension-resolution-loader。
¥Module customization hooks provide a mechanism for customizing the ESM specifier resolution algorithm. An example that provides CommonJS-style resolution for ESM specifiers is commonjs-extension-resolution-loader.