简介
随着越来越多的 Node.js 项目采用 ESM 作为模块系统,一些较旧的 CommonJS 模块依然被广泛使用。由于这两者的模块系统存在一些差异,我们可能会面临引入 CommonJS 模块到 ESM 项目中的挑战。
这种兼容性问题主要表现为:
- ESM 模块系统使用
import
和export
,而 CommonJS 使用require
和module.exports
。 - Node.js 对文件扩展名(如
.js
,.mjs
,.cjs
)的处理方式不同,可能会导致加载错误。
在 ESM 中引入 CommonJS 模块的几种方式
方法 1:使用 .cjs
后缀和 require()
(同步加载)
这是最推荐的方式,它让你明确指定文件是 CommonJS 模块,并允许你使用同步的 require()
来导入模块。
步骤:
- 确保 CommonJS 模块使用
.cjs
后缀。 - 使用
createRequire
方法来引入 CommonJS 模块。
javascript
// cjs-file.cjs
module.exports = {
sayHi(name) {
console.log(`Hi, ${name} from CommonJS`);
}
};
javascript
// esm-file.js
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const cjs = require('./cjs-file.cjs');
cjs.sayHi('Alice');
优点:
- 同步加载,代码简单直观。
- 兼容性好,适用于大多数 Node.js 项目。
方法 2:使用动态 import()
(异步加载)
当你不能或不想使用 .cjs
后缀时,可以使用动态 import()
来加载 CommonJS 模块。由于 import()
是异步的,你需要使用 await
或 .then()
来处理加载。
dart
// esm-file.js
const cjsModule = await import('./cjs-file.js'); // 动态导入
cjsModule.default.sayHi('Alice');
优点:
- 灵活性高,可以按需加载模块。
- 不要求模块使用
.cjs
后缀。
缺点:
- 异步加载,代码稍显复杂。
- 需要使用
default
属性来访问 CommonJS 导出的内容。