与 CommonJS 的互操作性¶
import 语句¶
import语句可以引用 ES 模块或 CommonJS 模块。
仅在 ES 模块中允许import 语句, 但是 CommonJS 中支持动态import()表达式来加载 ES 模块。
当导入CommonJS 模块时,module.exports对象被作为默认导出提供。
可以使用静态分析提供的命名导出,以方便更好的生态系统兼容性。
require¶
CommonJS 模块require总是将它引用的文件视为 CommonJS。
不支持使用require加载 ES 模块,因为 ES 模块具有异步执行。
相反,使用import()从 CommonJS 模块加载 ES 模块。
CommonJS 名称空间¶
CommonJS 模块由一个模块组成。导出对象,该对象可以是任何类型。
当导入 CommonJS 模块时,可以使用 ES 模块默认导入或对应的 sugar 语法可靠地导入:
CommonJS 模块的 ECMAScript 模块命名空间表示形式始终是一个带有default导出键的命名空间,该导出键指向 CommonJS 的module.exports值。
当使用import * as m from 'cjs'或动态导入时,可以直接观察到这个模块命名空间外来对象:
为了更好地兼容 JS 生态系统中的现有使用,Node.js 还试图确定每个导入的 CommonJS 模块的 CommonJS 命名导出,并使用静态分析过程将它们作为单独的 ES 模块导出提供。
例如,考虑这样一个 CommonJS 模块:
例如,考虑一个 CommonJS 模块:前面的模块支持 ES 模块中的命名导入:
从上一个记录模块名称空间外来对象的示例中可以看出,导入模块时,name导出是从module.exports对象中复制出来的,并直接在 ES 模块名称空间上设置。
对于这些已命名的导出,不会检测到添加到module.exports中的实时绑定更新或新导出。
命名导出的检测基于通用语法模式,但并不总是正确地检测命名导出。 在这些情况下,使用上面描述的默认导入表单可能是更好的选择。
Named exports detection covers many common export patterns, reexport patterns and build tool and transpiler outputs. See cjs-module-lexer for the exact semantics implemented.
命名导出检测包括许多常见的导出模式、再导出模式以及构建工具和转译器输出。 具体实现的语义请参见cjs-module-lexer。
ES 模块和 CommonJS 的区别¶
No require, exports, or module.exports¶
在大多数情况下,ES 模块import可以用来加载 CommonJS 模块。
如果需要,可以使用module.createRequire()在 ES 模块中构造require函数
No __filename or __dirname¶
这些 CommonJS 变量在 ES 模块中不可用。
__filename 和 __dirname 用例可以通过import.meta.url复制
无加载插件¶
ES 模块导入目前不支持Addons。
它们可以用module.createRequire()或process.dlopen来加载。
No require.resolve¶
相对解析可以通过new URL('./local', import.meta.url)来处理。
对于一个完整的require.resolve替换,有一个标记的实验import.meta.resolve API。
也可以使用module.createRequire()。
No NODE_PATH¶
NODE_PATH不是解析import说明符的一部分。
如果需要这种行为,请使用符号链接。
No require.extensions¶
require.extensions不会被import使用。
我们期望将来加载器钩子可以提供这个工作流。
No require.cache¶
require.cache不会被import使用,因为 ES 模块加载器有自己单独的缓存。