模块解析和加载


¥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 文本文件。

      ¥.json files are treated as JSON text files.

    • .node 文件被解释为加载了 process.dlopen() 的编译插件模块。

      ¥.node files are interpreted as compiled addon modules loaded with process.dlopen().

    • .ts.mts.cts 文件会被视为 TypeScript 文本文件。

      ¥.ts, .mts and .cts files 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-level await).

当通过静态 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:// and data: URLs as specifiers by default.

  • 加载:

    ¥Loading:

    • .json 文件会被视为 JSON 文本文件。导入 JSON 模块时,必须指定导入类型属性(例如 import json from './data.json' with { type: 'json' })。

      ¥.json files 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() 加载的已编译插件模块。

      ¥.node files are interpreted as compiled addon modules loaded with process.dlopen(), if --experimental-addon-modules is enabled.

    • .ts.mts.cts 文件会被视为 TypeScript 文本文件。

      ¥.ts, .mts and .cts files are treated as TypeScript text files.

    • 它只接受 JavaScript 文本文件的 .js.mjs.cjs 扩展名。

      ¥It accepts only .js, .mjs, and .cjs extensions for JavaScript text files.

    • .wasm 文件会被视为 WebAssembly 模块

      ¥.wasm files are treated as WebAssembly modules.

    • 任何其他文件扩展名都会导致 ERR_UNKNOWN_FILE_EXTENSION 错误。可以通过 自定义钩子 实现添加其他文件扩展名。

      ¥Any other file extensions will result in a ERR_UNKNOWN_FILE_EXTENSION error. 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 the cjs-module-lexer to 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.