模块解析和加载
¥Module resolution and loading
Node.js 有两种模块解析和加载方式,具体取决于模块的请求方式。
¥Node.js has two types of module resolution and loading, chosen based on how the module is requested.
当通过 require() 请求模块时(CommonJS 模块默认可用,并且可以使用 createRequire() 在 CommonJS 和 ES 模块中动态生成):
¥When a module is requested via require() (available by default in CommonJS modules,
and can be dynamically generated using createRequire() in both CommonJS and ES Modules):
-
解析:
¥Resolution:
-
由
require()发起的解析支持 文件夹作为模块。¥The resolution initiated by
require()supports folders as modules. -
解析说明符时,如果找不到完全匹配项,
require()将尝试添加扩展名(.js、.json,最后是.node),然后尝试解析 文件夹作为模块。¥When resolving a specifier, if no exact match is found,
require()will try to add extensions (.js,.json, and finally.node) and then attempt to resolve folders as modules. -
默认情况下,它不支持使用 URL 作为指定符。
¥It does not support URLs as specifiers by default.
-
-
加载:
¥Loading:
-
.json文件会被视为 JSON 文本文件。¥
.jsonfiles are treated as JSON text files. -
.node文件被解释为加载了process.dlopen()的编译插件模块。¥
.nodefiles are interpreted as compiled addon modules loaded withprocess.dlopen(). -
.ts、.mts和.cts文件会被视为 TypeScript 文本文件。¥
.ts,.mtsand.ctsfiles are treated as TypeScript text files. -
任何其他扩展名或无扩展名的文件都被视为 JavaScript 文本文件。
¥Files with any other extension, or without extensions, are treated as JavaScript text files.
-
只有当 ECMAScript 模块 及其依赖是同步的(即它们不包含顶层
await)时,require()才能用于 从 CommonJS 模块加载 ECMAScript 模块。¥
require()can only be used to load ECMAScript modules from CommonJS modules if the ECMAScript module and its dependencies are synchronous (i.e. they do not contain top-levelawait).
-
当通过静态 import 语句(仅在 ES 模块中可用)或 import() 表达式(CommonJS 和 ES 模块均可用)请求模块时:
¥When a module is requested via static import statements (only available in ES Modules)
or import() expressions (available in both CommonJS and ES Modules):
-
解析:
¥Resolution:
-
import/import()的解析不支持将文件夹作为模块,目录索引(例如'./startup/index.js')必须完整指定。¥The resolution of
import/import()does not support folders as modules, directory indexes (e.g.'./startup/index.js') must be fully specified. -
它不执行扩展名搜索。当说明符是相对或绝对的文件 URL 时,必须提供文件扩展名。
¥It does not perform extension searching. A file extension must be provided when the specifier is a relative or absolute file URL.
-
默认情况下,它支持使用
file://和data:URL 作为指定符。¥It supports
file://anddata:URLs as specifiers by default.
-
-
加载:
¥Loading:
-
.json文件会被视为 JSON 文本文件。导入 JSON 模块时,必须指定导入类型属性(例如import json from './data.json' with { type: 'json' })。¥
.jsonfiles are treated as JSON text files. When importing JSON modules, an import type attribute is required (e.g.import json from './data.json' with { type: 'json' }). -
如果启用了
--experimental-addon-modules,则.node文件会被解释为使用process.dlopen()加载的已编译插件模块。¥
.nodefiles are interpreted as compiled addon modules loaded withprocess.dlopen(), if--experimental-addon-modulesis enabled. -
.ts、.mts和.cts文件会被视为 TypeScript 文本文件。¥
.ts,.mtsand.ctsfiles are treated as TypeScript text files. -
它只接受 JavaScript 文本文件的
.js、.mjs和.cjs扩展名。¥It accepts only
.js,.mjs, and.cjsextensions for JavaScript text files. -
.wasm文件会被视为 WebAssembly 模块。¥
.wasmfiles are treated as WebAssembly modules. -
任何其他文件扩展名都会导致
ERR_UNKNOWN_FILE_EXTENSION错误。可以通过 自定义钩子 实现添加其他文件扩展名。¥Any other file extensions will result in a
ERR_UNKNOWN_FILE_EXTENSIONerror. Additional file extensions can be facilitated via customization hooks. -
import/import()可用于加载 JavaScript CommonJS 模块。这样的模块通过cjs-module-lexer来尝试识别命名的导出,如果可以通过静态分析确定的话是可用的。¥
import/import()can be used to load JavaScript CommonJS modules. Such modules are passed through thecjs-module-lexerto try to identify named exports, which are available if they can be determined through static analysis.
-
无论模块的请求方式如何,都可以使用 自定义钩子 自定义解析和加载过程。
¥Regardless of how a module is requested, the resolution and loading process can be customized using customization hooks.