Last updated on September 11
Node.js 有两个模块系统:CJS 和 ESM
.mjs 的文件(无论 package.json 中 type 配置为何值)package.json 的 type 为 module,拓展名为 .js 的文件import() 调用.cjs 的文件(无论 package.json 中 type 配置为何值)package.json 的 type 为 commonjs 或不包含 type 字段时(默认为 commonjs),拓展名为 .js 的文件require() 调用.mjs,.cjs,.json,.node,.js 时(当父级 package.json 的 type 为 module 时,不作为程序的命令行入口时,这些文件在被要求时才会被识别为 CJS 模块)
require() 的同步特性,不能用它来加载 ESM 模块文件,会产生 ERR_REQUIRE_ESM 错误。CommonJS module loader
this 指向当前模块require() 调用.js,.json,最后是 .node),然后尝试解析文件夹为模块.json 作为 JSON 文本文件.node 文件将被解释为用 process.dlopen() 加载的已编译附加模块ECMAScript module loader
异步(asynchronous)
不支持 monkey patchable。但可以通过 Loader Hooks 进行定制
编译时输出接口
import 引用关系推导出来的this 指向 undefined负责处理 import statements 和 import() 表达式
不支持文件夹作为模块,目录索引必须完全指定(例如:./startup/index.js)
不做拓展名搜索。当指定是一个相对或绝对的文件 URL 时,必须提供文件拓展名
可以加载 JSON 模块,但需要一个导入断言
// index.mjs
// An import assertion in a static import
import info from './package.json' assert { type: 'json' }
// An import assertion in a dynamic import
const { default: info } = await import('./package.json', { assert: { type: 'json' } })
只接受以 .js,.mjs,和 .cjs 为拓展名的 JavaScript 文本文件
可以用来加载 JavaScript CJS 模块。这些模块通过 cjs-module-lexer 来尝试识别命名的导出。如果可以通过静态分析确定,那么这些导出是可用的,导入的 CJS 模块将其 URL 转换为绝对路径,然后通过 CJS module loader 加载。
require(X),X 来自路径 Y 的模块
/ 开头。设置 Y 为文件系统根目录./ 或 / 或 ../ 开头。
# 开头
如果没有找到准确的文件名,Node.js 将尝试加载所需的文件名,并添加扩展名:.js、.json,最后是 .node。当加载具有不同扩展名的文件时(例如:.cjs),必须将其全名传递给 require(),包括其文件扩展名(例如:require('./file.cjs'))