Modules: Packages
包是由
package.json文件描述的文件夹树。该包由包含该package.json文件的文件夹和所有子文件夹组成,直到下一个包含另一个package.json文件的文件夹或名为node_modules的文件夹。
确定模块
当作为初始输入传递到
node时,或者当语import句或import()表达式引用时,
Node.js会将以下内容视为 ES 模块:
.mjs具有扩展名的文件。- 当最近的父
package.json文件包含值为 的"module"顶级"type"字段时,.js具有扩展名的文件。 - 字符串作为参数传入
--eval,或通过管道传递到nodeSTDINvia ,标志为--input-type=module - 使用
--experimental-detect-module时,包含语法的代码仅成功解析为ES模块,例如import或export语句或import.meta,没有明确标记应如何解释它。显式标记是.mjsor.cjs扩展名、package.json"type"带有"module"or"commonjs"值或--input-typeor--experimental-default-type标志的字段。CommonJS 或 ES 模块都支持动态import()表达式,并且不会导致文件被视为 ES 模块。
Node.js会将以下内容视为 CommonJS:
.cjs具有扩展名的文件。- 当最近的父
package.json文件包含值为"commonjs"顶级"type"字段时,.js具有扩展名的文件。 - 字符串作为参数传入
--eval或通过管道传递到nodeSTDINvia标志为--input-type=commonjs
此标志当前默认为 "commonjs" ,但将来可能会更改为默认为 "module" 。出于这个原因,最好尽可能明确;特别是,包作者应始终在其 package.json 文件中包含该 "type" 字段,即使在所有源代码都是 CommonJS 的包中也是如此。明确包的 type 包将使包面向未来,以防默认Node.js类型发生更改,并且它还将使构建工具和加载器更容易确定应如何解释包中的文件。
模块加载解析
Node.js有两个系统,用于解析模块和加载模块。
CommonJS 模块加载器:
- 它是完全同步的。
- 它负责处理 require() 呼叫。
- 它是猴子可修补的
- 它支持将文件夹作为模块。
- 解析说明符时,如果没有找到完全匹配项,它将尝试添加扩展名(
.js、.json和.node),然后尝试将文件夹解析为模块。 - 它被视为 .json JSON 文本文件。
.node文件被解释为加载了process.dlopen()- 它将所有缺少
.json或.node扩展名的文件视为JavaScript文本文件。 - 它只能用于从 CommonJS 模块加载 ECMASCript 模块,前提是模块图是同步的(不包含顶级
await)启用--experimental-require-module。当用于加载不是 ECMAScript 模块的 JavaScript 文本文件时,该文件将作为 CommonJS 模块加载。
ECMAScript 模块加载器:
- 它是异步的,除非它用于加载 require() 的模块。
- 它负责处理 import 语句和 import() 表达式。
- 它不是猴子可修补的,可以使用加载器钩子进行自定义。
- 它不支持文件夹作为模块,目录索引(例如 './startup/index.js' )必须完全指定。
- 它不进行扩展搜索。当说明符是相对或绝对文件 URL 时,必须提供文件扩展名。
- 可以加载 JSON 模块,但需要导入断言。
- 它只接受 JavaScript 文本文件的扩展
.js.cjs.mjs - 它可用于加载 JavaScript CommonJS 模块。这些模块通过
cjs-module-lexer尝试识别命名导出,如果可以通过静态分析确定它们,则可以使用这些导出。导入的 CommonJS 模块的 URL 转换为绝对路径,然后通过 CommonJS 模块加载器加载。
package.json 和文件扩展名
- 在包中,该
package.json"type"字段定义Node.js应如何解释.js文件。如果package.json文件没有"type"字段,.js则文件将被视为 CommonJS。 package.json"type"值 为"module"指示Node.js使用 ES 模块语法将该包中的 .js 文件解析。- 该
"type"字段不仅适用于初始入口点 (node my-app.js),还适用于语import句和import()表达式引用的文件。
结尾 .mjs 的文件始终作为 ES 模块加载,而不考虑最近的父级 package.json 。 结尾 .cjs 的文件始终以 CommonJS 的形式加载,而不考虑最近的父 package.json 级。
js
import './legacy-file.cjs';
// .cjs 始终作为 CommonJS 加载。
import 'commonjs-package/src/index.mjs';
// .mjs 始终作为 ES 模块加载。
CodeVortex