跳到主要内容

CommonJS 与 ES6 模块混用问题

我们目前测试的是 Node.js 环境下的

Node 会识别文件的后缀,如果是 cjs 则默认 commonJS,如果是 mjs 则是 ES6

如果没有设置则根据packjson.json中的 type 来判断类型,注意需要控制main为正确的入口文件才可以

ES6 引入 CommonJS 模块

假设我们声明了一个commonExport.cjs的文件,其文件是 CommonJS 导出规则

function say() {
console.log("Hello World");
}
exports.say1 = say;
exports.say2 = "123";

然后在使用 ES 模块的文件中中导入

import commonExport from "./commonExport.cjs";

console.log("commonExport", commonExport);
// commonExport { say1: [Function: say], say2: '123' }

可以发现有正常引用

CommonJS 引入 ES6 模块

如果我们直接了当的在一个 CommonJS 文件中导入 ES6 模块,会报错

const esExport = require("./esExport.js");

console.log("esExport", esExport);

提示错误

Error [ERR_REQUIRE_ESM]: require() of ES Module esExport.js from commonIndex.cjs not supported.
Instead change the require of esExport.js in commonIndex.cjs to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (commonIndex.cjs:1:16) {
code: 'ERR_REQUIRE_ESM'
}

告诉了我们无法使用 require 函数,但是可以使用动态 import 函数来进行导入,我们尝试一下

import("./esExport.js").then((res) => {
console.log("res", res);
//res [Module: null prototype] {
// default: { name: 'person export' },
// eat: [Function: eat],
// name: 'Li MeiMei',
// say: [Function: say]
// }
});

可以发现 ES6 的默认导出挂载到了 default 上,而其他普通导出的直接挂载到了对象上

关于该动态 import 函数属于 Node.js 的支持,具体可以参考Interoperability with CommonJS

import statements

An import statement can reference an ES module or a CommonJS module.
import statements are permitted only in ES modules
but dynamic import() expressions are supported in CommonJS for loading ES modules.

When importing CommonJS modules
the module.exports object is provided as the default export.
Named exports may be available
provided by static analysis as a convenience for better ecosystem compatibility.