CommonJS模块
默认情况下,Node.js 会将以下内容视为 CommonJS 模块:
- 带有
.cjs
扩展名的文件。 - 当最近的父文件包含值为 的顶级字段时,具有
.js
扩展名的文件。package.json
中["type"](https://nodejs.org/api/packages.html#type)"commonjs"
- 字符串作为参数传入
--evalor --print
,或通过管道传送到node via STDIN,带有标志--input-type=commonjs
。- 它是完全同步的。
- 它支持文件夹作为模块。
- 解析说明符时,如果未找到完全匹配,它将尝试添加扩展名(.js、、.json和 finally .node),然后尝试将 文件夹解析为模块。
- 它被视为.jsonJSON 文本文件。
- .node文件被解释为加载了 process.dlopen().
- 它将所有缺少.json或.node扩展名的文件视为 JavaScript 文本文件。
- 它不能用于加载 ECMAScript 模块(尽管可以 从 CommonJS 模块加载 ECMASCript 模块)。当用于加载不是 ECMAScript 模块的 JavaScript 文本文件时,它将作为 CommonJS 模块加载。
ES6 模块
默认情况下,Node.js 会将以下内容视为 CommonJS 模块:
- 带有
.mjs
扩展名的文件。 - 当最近的父文件包含值为 的顶级字段时,具有
.js
扩展名的文件。package.json["type"](https://nodejs.org/api/packages.html#type)"module"
- 使用标志作为参数传入
--eval
或通过管道传递给nodevia的字符串。STDIN--input-type=module
- 它是异步的。
- 它负责处理import语句和import()表达式。
- 它不是猴子可修补的,可以使用loader hooks进行自定义。
- 它不支持文件夹作为模块, ‘./startup/index.js’必须完全指定目录索引(例如)。
- 它不进行扩展搜索。当说明符是相对或绝对文件 URL 时,必须提供文件扩展名。
- 它可以加载 JSON 模块,但需要导入断言。
- 它只接受JavaScript 文本文件的.js、.mjs和.cjs扩展名。
- 它可用于加载 JavaScript CommonJS 模块。此类模块通过传递cjs-module-lexer以尝试识别命名导出,如果它们可以通过静态分析确定,则它们是可用的。导入的 CommonJS 模块将其 URL 转换为绝对路径,然后通过 CommonJS 模块加载器加载。
CommonJS 模块加载 ES6 模块
CommonJS 的require()
命令不能加载 ES6 模块,会报错,只能使用import()
这个方法加载。
await import('./my-app.mjs');
ES6 模块加载 CommonJS 模块
ES6 模块的import
命令可以加载 CommonJS 模块,但是只能整体加载,不能只加载单一的输出项。
// 正确
import packageMain from 'commonjs-package';
// 报错
import { method } from 'commonjs-package';
这是因为 ES6 模块需要支持静态代码分析,而 CommonJS 模块的输出接口是module.exports
,是一个对象,无法被静态分析,所以只能整体加载。
加载单一的输出项,可以写成下面这样。
import packageMain from 'commonjs-package';
const { method } = packageMain;
同时支持两种格式的模块
模块封装
- 原始模块是 ES6 格式:要给出一个整体输出接口,比如
export default obj
,使得 CommonJS 可以用import()
进行加载。 - 原始模块是 CommonJS 格式:那么可以加一个包装层。
上面代码先整体输入 CommonJS 模块,然后再根据需要输出具名接口。import cjsModule from '../index.js';
export const foo = cjsModule.foo;
入口文件暴露
可以把这个文件的后缀名改为.mjs
,或者将它放在一个子目录,再在这个子目录里面放一个单独的package.json文件,指明{ type: "module" }
。
还可以在package.json
文件指定export
字段,分别指定两种规范的入口文件
"exports":{
"require": "./index.js",
"import": "./esm/wrapper.js"
}