- assert断言
- async_hooks异步钩子
- buffer缓冲区
- C++插件
- C/C++插件(使用Node-API)
- C++嵌入器
- child_process子进程
- cluster集群
- CLI命令行
- console控制台
- Corepack核心包
- crypto加密
- debugger调试器
- deprecation弃用
- dgram数据报
- diagnostics_channel诊断通道
- dns域名服务器
- domain域
- Error错误
- events事件触发器
- fs文件系统
- global全局变量
- http超文本传输协议
- http2超文本传输协议2.0
- https安全超文本传输协议
- inspector检查器
- Intl国际化
- module模块
- module/cjsCommonJS模块
- module/esmECMAScript模块
- module/package包模块
- net网络
- os操作系统
- path路径
- perf_hooks性能钩子
- policy安全策略
- process进程
- punycode域名代码
- querystring查询字符串
- readline逐行读取
- repl交互式解释器
- report诊断报告
- stream流
- string_decoder字符串解码器
- timers定时器
- tls安全传输层
- trace_events跟踪事件
- tty终端
- url网址
- util实用工具
- v8引擎
- vm虚拟机
- wasi网络汇编系统接口
- worker_threads工作线程
- zlib压缩
Node.js v14.20.0 文档
- Node.js 14.20.0
- ► 目录
-
►
索引
- assert 断言
- async_hooks 异步钩子
- buffer 缓冲区
- C++插件
- C/C++插件(使用Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- 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 包模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- policy 安全策略
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- stream 流
- string_decoder 字符串解码器
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- worker_threads 工作线程
- zlib 压缩
- ► 其他版本
- 文档搜索
- 会员登录
目录
ECMAScript 模块#
介绍#
ECMAScript 模块是来打包 JavaScript 代码以供重用的官方标准格式。
模块使用各种 import
和 export
语句定义。
启用#
Node.js 默认将 JavaScript 代码视为 CommonJS 模块。
作者可以通过 .mjs
文件扩展名、package.json
"type"
字段、或 --input-type
标志告诉 Node.js 将 JavaScript 代码视为 ECMAScript 模块。
有关更多详细信息,请参阅包模块。
包#
此章节已移至包模块。
import 说明符#
术语#
import
语句的说明符是 from
关键字之后的字符串,例如 import { sep } from 'path'
中的 'path'
。
说明符也用于 export from
语句,并作为 import()
表达式的参数。
强制的文件扩展名#
当使用 import
关键字解析相对或绝对的说明符时,必须提供文件扩展名。
还必须完全指定目录索引(例如 './startup/index.js'
)。
URL#
ES 模块被解析并缓存为 URL。
这意味着包含 #
和 ?
等特殊字符的文件需要转义。
file: URL#
如果用于解析模块的 import
说明符具有不同的查询或片段,则会多次加载模块。
data: 导入#
data:
URL 支持使用以下 MIME 类型导入:
node: 导入#
支持 node:
URL 作为加载 Node.js 内置模块的替代方法。
此 URL 协议允许有效的绝对的 URL 字符串引用内置模块。
内置模块#
核心模块提供了其公共 API 的命名导出。
还提供了默认导出,其是 CommonJS 导出的值。
默认导出可用于修改命名导出等。
内置模块的命名导出仅通过调用 module.syncBuiltinESMExports()
进行更新。
import() 表达式#
动态的 import()
在 CommonJS 和 ES 模块中都受支持。
在 CommonJS 模块中它可以用来加载 ES 模块。
import.meta
#
import.meta
元属性是包含以下属性的 Object
。
import.meta.url
#
这与提供当前模块文件 URL 的浏览器中的定义完全相同。
import.meta.resolve(specifier[, parent])
#
此特性仅在启用 --experimental-import-meta-resolve
命令标志时可用。
与 CommonJS 的互操作性#
import 声明#
import
语句可以引用 ES 模块或 CommonJS 模块。
import
语句只允许在 ES 模块中使用,但 CommonJS 支持动态 import()
表达式来加载 ES 模块。
require
#
CommonJS 模块 require
总是将它引用的文件视为 CommonJS。
CommonJS 命名空间#
CommonJS 模块由可以是任何类型的 module.exports
对象组成。
ES 模块和 CommonJS 之间的差异#
没有 require、exports 或 module.exports#
在大多数情况下,可以使用 ES 模块 import
加载 CommonJS 模块。
没有 __filename 或 __dirname#
这些 CommonJS 变量在 ES 模块中不可用。
没有 JSON 模块加载#
JSON 导入仍处于实验阶段,仅通过 --experimental-json-modules
标志支持。
没有原生模块加载#
ES 模块导入当前不支持原生模块。
没有 require.resolve#
相对解析可以通过 new URL('./local', import.meta.url)
处理。
没有 NODE_PATH#
NODE_PATH
不是解析 import
说明符的一部分。
如果需要这种行为,则使用符号链接。
没有 require.extensions#
require.extensions
没有被 import
使用。
期望加载器钩子在未来可以提供这个工作流。
没有 require.cache#
require.cache
没有被 import
使用,因为 ES 模块加载器有自己独立的缓存。
JSON 模块#
目前导入 JSON 模块仅支持 commonjs
模式,并且使用 CJS 加载器加载。
WHATWG JSON 模块规范仍在标准化中,并且通过在运行 Node.js 时包含额外的标志 --experimental-json-modules
进行实验性地支持。
Wasm 模块#
在 --experimental-wasm-modules
标志下支持导入 Web Assembly 模块,允许将任何 .wasm
文件作为普通模块导入,同时还支持它们的模块导入。
顶层的 await#
await
关键字可以用在 ECMAScript 模块的顶层主体中。
加载器#
注意:此 API 目前正在重新设计,并将继续更改。
钩子#
resolve(specifier, context, defaultResolve)
#
resolve
钩子返回给定模块说明符和父 URL 的解析文件 URL。
模块说明符是 import
语句或 import()
表达式中的字符串,父 URL 是导入此模块的 URL,如果这是应用程序的主要入口点,则为 undefined
getFormat(url, context, defaultGetFormat)
#
getFormat
钩子提供了一种方式来定义确定网址应如何解释的自定义方法。
返回的 format
也会影响解析时模块的可接受的源值形式。
这可以是以下之一:
getSource(url, context, defaultGetSource)
#
getSource
钩子提供了一种方法来定义用于检索 ES 模块说明符的源代码的自定义方法。
这将允许加载器潜在地避免从磁盘读取文件。
transformSource(source, context, defaultTransformSource)
#
transformSource
钩子提供了一种在加载源字符串之后但在 Node.js 对其进行任何操作之前修改加载的 ES 模块文件的源代码的方法。
getGlobalPreloadCode()
#
有时可能需要在应用程序运行所在的同一全局范围内运行一些代码。 此钩子允许返回在启动时作为宽松模式脚本运行的字符串。
示例#
各种加载器钩子可以一起使用来完成对 Node.js 代码加载和评估行为的广泛定制。
HTTPS 加载器#
在当前的 Node.js 中,不支持以 https://
开头的说明符。
下面的加载器注册钩子以启用对此类说明符的基本支持。
虽然这似乎是对 Node.js 核心功能的重大改进,但实际使用这个加载器有很大的缺点:性能比从磁盘加载文件慢得多,没有缓存,也没有安全性。
转译器加载器#
可以使用 transformSource
钩子将 Node.js 无法理解的格式的源转换为 JavaScript。
但是,在调用该钩子之前,其他钩子需要告诉 Node.js 不要在未知文件类型上抛出错误;并告诉 Node.js 如何加载这种新文件类型。
解析算法#
特性#
解析器具有以下属性:
解析器算法#
加载 ES 模块说明符的算法通过下面的 ESM_RESOLVE 方法给出。 它返回相对于 parentURL 的模块说明符的解析 URL。
解析器算法规范#
ESM_RESOLVE(specifier, parentURL)
- Let resolved be undefined.
- If specifier is a valid URL, then
- Set resolved to the result of parsing and reserializing specifier as a URL.
- Otherwise, if specifier starts with "/", "./" or "../", then
- Set resolved to the URL resolution of specifier relative to parentURL.
- Otherwise, if specifier starts with "#", then
- Set resolved to the destructured value of the result of PACKAGE_IMPORTS_RESOLVE(specifier, parentURL, defaultConditions).
- Otherwise,
- Note: specifier is now a bare specifier.
- Set resolved the result of PACKAGE_RESOLVE(specifier, parentURL).
- 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.
- Set resolved to the real path of resolved.
- Let format be the result of ESM_FORMAT(resolved).
- Load resolved as module format, format.
- Return resolved.
PACKAGE_RESOLVE(packageSpecifier, parentURL)
- Let packageName be undefined.
- If packageSpecifier is an empty string, then
- Throw an Invalid Module Specifier error.
- If packageSpecifier does not start with "@", then
- Set packageName to the substring of packageSpecifier until the first "/" separator or the end of the string.
- Otherwise,
- If packageSpecifier does not contain a "/" separator, then
- Throw an Invalid Module Specifier error.
- Set packageName to the substring of packageSpecifier until the second "/" separator or the end of the string.
- If packageName starts with "." or contains "\" or "%", then
- Throw an Invalid Module Specifier error.
- Let packageSubpath be "." concatenated with the substring of packageSpecifier from the position at the length of packageName.
- Let selfUrl be the result of PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL).
- If selfUrl is not undefined, return selfUrl.
- If packageSubpath is "." and packageName is a Node.js builtin module, then
- Return the string "node:" concatenated with packageSpecifier.
- While parentURL is not the file system root,
- Let packageURL be the URL resolution of "node_modules/" concatenated with packageSpecifier, relative to parentURL.
- Set parentURL to the parent folder URL of parentURL.
- If the folder at packageURL does not exist, then
- Set parentURL to the parent URL path of parentURL.
- Continue the next loop iteration.
- Let pjson be the result of READ_PACKAGE_JSON(packageURL).
- If pjson is not null and pjson.exports is not null or undefined, then
- Let exports be pjson.exports.
- Return the resolved destructured value of the result of PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions).
- Otherwise, if packageSubpath is equal to ".", then
- Return the result applying the legacy LOAD_AS_DIRECTORY CommonJS resolver to packageURL, throwing a Module Not Found error for no resolution.
- Otherwise,
- Return the URL resolution of packageSubpath in packageURL.
- Throw a Module Not Found error.
PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL)
- Let packageURL be the result of READ_PACKAGE_SCOPE(parentURL).
- If packageURL is null, then
- Return undefined.
- Let pjson be the result of READ_PACKAGE_JSON(packageURL).
- If pjson is null or if pjson.exports is null or undefined, then
- Return undefined.
- If pjson.name is equal to packageName, then
- Return the resolved destructured value of the result of PACKAGE_EXPORTS_RESOLVE(packageURL, subpath, pjson.exports, defaultConditions).
- Otherwise, return undefined.
PACKAGE_EXPORTS_RESOLVE(packageURL, subpath, exports, conditions)
- 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
- Let mainExport be undefined.
- If exports is a String or Array, or an Object containing no keys starting with ".", then
- Set mainExport to exports.
- Otherwise if exports is an Object containing a "." property, then
- Set mainExport to exports["."].
- If mainExport is not undefined, then
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, mainExport, "", false, false, conditions).
- If resolved is not null or undefined, then
- Return resolved.
- Otherwise, if exports is an Object and all keys of exports start with ".", then
- Let matchKey be the string "./" concatenated with subpath.
- Let resolvedMatch be result of PACKAGE_IMPORTS_EXPORTS_RESOLVE( matchKey, exports, packageURL, false, conditions).
- If resolvedMatch.resolve is not null or undefined, then
- Return resolvedMatch.
- 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.
- Let packageURL be the result of READ_PACKAGE_SCOPE(parentURL).
- If packageURL is not null, then
- Let pjson be the result of READ_PACKAGE_JSON(packageURL).
- If pjson.imports is a non-null Object, then
- Let resolvedMatch be the result of PACKAGE_IMPORTS_EXPORTS_RESOLVE(specifier, pjson.imports, packageURL, true, conditions).
- If resolvedMatch.resolve is not null or undefined, then
- Return resolvedMatch.
- Throw a Package Import Not Defined error.
PACKAGE_IMPORTS_EXPORTS_RESOLVE(matchKey, matchObj, packageURL, isImports, conditions)
- If matchKey is a key of matchObj and does not end in "/" or contain "*", then
- Let target be the value of matchObj[matchKey].
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, "", false, isImports, conditions).
- Return the object { resolved, exact: true }.
- Let expansionKeys be the list of keys of matchObj either ending in "/" or containing only a single "*", sorted by the sorting function PATTERN_KEY_COMPARE which orders in descending order of specificity.
- For each key expansionKey in expansionKeys, do
- Let patternBase be null.
- If expansionKey contains "*", set patternBase to the substring of expansionKey up to but excluding the first "*" character.
- If patternBase is not null and matchKey starts with but is not equal to patternBase, then
- Let patternTrailer be the substring of expansionKey from the index after the first "*" character.
- 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
- Let target be the value of matchObj[expansionKey].
- Let subpath 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.
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, subpath, true, isImports, conditions).
- Return the object { resolved, exact: true }.
- Otherwise if patternBase is null and matchKey starts with expansionKey, then
- Let target be the value of matchObj[expansionKey].
- Let subpath be the substring of matchKey starting at the index of the length of expansionKey.
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, subpath, false, isImports, conditions).
- Return the object { resolved, exact: false }.
- Return the object { resolved: null, exact: true }.
PATTERN_KEY_COMPARE(keyA, keyB)
- Assert: keyA ends with "/" or contains only a single "*".
- Assert: keyB ends with "/" or contains only a single "*".
- Let baseLengthA be the index of "*" in keyA plus one, if keyA contains "*", or the length of keyA otherwise.
- Let baseLengthB be the index of "*" in keyB plus one, if keyB contains "*", or the length of keyB otherwise.
- If baseLengthA is greater than baseLengthB, return -1.
- If baseLengthB is greater than baseLengthA, return 1.
- If keyA does not contain "*", return 1.
- If keyB does not contain "*", return -1.
- If the length of keyA is greater than the length of keyB, return -1.
- If the length of keyB is greater than the length of keyA, return 1.
- Return 0.
PACKAGE_TARGET_RESOLVE(packageURL, target, subpath, pattern, internal, conditions)
- If target is a String, then
- If pattern is false, subpath has non-zero length and target does not end with "/", throw an Invalid Module Specifier error.
- If target does not start with "./", then
- If internal is true and target does not start with "../" or "/" and is not a valid URL, then
- If pattern is true, then
- Return PACKAGE_RESOLVE(target with every instance of "*" replaced by subpath, packageURL + "/")_.
- Return PACKAGE_RESOLVE(target + subpath, packageURL + "/")_.
- Otherwise, throw an Invalid Package Target error.
- If target split on "/" or "\" contains any ".", ".." or "node_modules" segments after the first segment, throw an Invalid Package Target error.
- Let resolvedTarget be the URL resolution of the concatenation of packageURL and target.
- Assert: resolvedTarget is contained in packageURL.
- If subpath split on "/" or "\" contains any ".", ".." or "node_modules" segments, throw an Invalid Module Specifier error.
- If pattern is true, then
- Return the URL resolution of resolvedTarget with every instance of "*" replaced with subpath.
- Otherwise,
- Return the URL resolution of the concatenation of subpath and resolvedTarget.
- Otherwise, if target is a non-null Object, then
- If exports contains any index property keys, as defined in ECMA-262 6.1.7 Array Index, throw an Invalid Package Configuration error.
- For each property p of target, in object insertion order as,
- If p equals "default" or conditions contains an entry for p, then
- Let targetValue be the value of the p property in target.
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, targetValue, subpath, pattern, internal, conditions).
- If resolved is equal to undefined, continue the loop.
- Return resolved.
- Return undefined.
- Otherwise, if target is an Array, then
- If _target.length is zero, return null.
- For each item targetValue in target, do
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, targetValue, subpath, pattern, internal, conditions), continuing the loop on any Invalid Package Target error.
- If resolved is undefined, continue the loop.
- Return resolved.
- Return or throw the last fallback resolution null return or error.
- Otherwise, if target is null, return null.
- Otherwise throw an Invalid Package Target error.
ESM_FORMAT(url)
- Assert: url corresponds to an existing file.
- Let pjson be the result of READ_PACKAGE_SCOPE(url).
- If url ends in ".mjs", then
- Return "module".
- If url ends in ".cjs", then
- Return "commonjs".
- If pjson?.type exists and is "module", then
- If url ends in ".js", then
- Return "module".
- Throw an Unsupported File Extension error.
- Otherwise,
- Throw an Unsupported File Extension error.
READ_PACKAGE_SCOPE(url)
- Let scopeURL be url.
- While scopeURL is not the file system root,
- Set scopeURL to the parent URL of scopeURL.
- If scopeURL ends in a "node_modules" path segment, return null.
- Let pjson be the result of READ_PACKAGE_JSON(scopeURL).
- If pjson is not null, then
- Return pjson.
- Return null.
READ_PACKAGE_JSON(packageURL)
- Let pjsonURL be the resolution of "package.json" within packageURL.
- If the file at pjsonURL does not exist, then
- Return null.
- If the file at packageURL does not parse as valid JSON, then
- Throw an Invalid Package Configuration error.
- Return the parsed JSON source of the file at pjsonURL.
自定义的 ESM 说明符解析算法#
当前的说明符解析不支持 CommonJS 加载器的所有默认行为。 行为差异之一是文件扩展名的自动解析以及导入具有索引文件的目录的能力。