跳至主要内容

@babel/plugin-transform-modules-commonjs

历史
版本变更
v7.14.0实现了 importInterop 选项
信息

此插件包含在 @babel/preset-envmodules 选项下

此插件将 ECMAScript 模块转换为 CommonJS。请注意,只有导入/导出语句(import "./mod.js")和导入表达式(import('./mod.js'))的语法会被转换,因为 Babel 不知道 ECMAScript 模块和 CommonJS 实现之间不同的解析算法。

示例

输入

JavaScript
export default 42;

输出

JavaScript
Object.defineProperty(exports, "__esModule", {
value: true,
});

exports.default = 42;

安装

npm install --save-dev @babel/plugin-transform-modules-commonjs

用法

JavaScript
// without options
{
"plugins": ["@babel/plugin-transform-modules-commonjs"]
}

// with options
{
"plugins": [
["@babel/plugin-transform-modules-commonjs", {
"allowTopLevelThis": true
}]
]
}

通过 CLI

Shell
babel --plugins @babel/plugin-transform-modules-commonjs script.js

通过 Node API

JavaScript
require("@babel/core").transformSync("code", {
plugins: ["@babel/plugin-transform-modules-commonjs"],
});

选项

importInterop

"babel" | "node" | "none",或 (specifier: string, requestingFilename: string | undefined) => "babel" | "node" | "none"。默认为 "babel"

CommonJS 模块和 ECMAScript 模块不完全兼容。但是,编译器、打包器和 JavaScript 运行时开发了不同的策略,以使它们尽可能地协同工作。

此选项指定 Babel 应使用哪种互操作策略。当它是一个函数时,Babel 会调用它,并传递导入说明符和导入器路径。例如,当编译包含 import { a } from 'b'/full/path/to/foo.js 文件时,Babel 将使用参数 ('b', '/full/path/to/foo.js') 调用它。

"babel"

当使用 babel 导出时,会导出一个不可枚举的 __esModule 属性。然后,使用此属性来确定导入默认导出还是包含默认导出。

JavaScript
import foo from "foo";
import { bar } from "bar";
foo;
bar;

// Is compiled to ...

"use strict";

function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj };
}

var _foo = _interopRequireDefault(require("foo"));
var _bar = require("bar");

_foo.default;
_bar.bar;

当使用此导入互操作时,如果导入模块和导入器模块都使用 Babel 编译,则它们的行为就像都没有编译一样。

这是默认行为。

"node"

当导入 CommonJS 文件(直接用 CommonJS 编写或使用编译器生成)时,Node.js 始终将 default 导出绑定到 module.exports 的值。

JavaScript
import foo from "foo";
import { bar } from "bar";
foo;
bar;

// Is compiled to ...

"use strict";

var _foo = require("foo");
var _bar = require("bar");

_foo;
_bar.bar;

这与 Node.js 的行为不完全相同,因为 Babel 允许访问 module.exports 的任何属性作为命名导出,而 Node.js 只允许导入 module.exports静态可分析属性。但是,任何在 Node.js 中工作的导入在使用 importInterop: "node" 编译 Babel 时也可以工作。

"none"

如果您知道导入的文件已使用将 default 导出存储在 exports.default 上的编译器(例如 Babel)进行了转换,则可以安全地省略 _interopRequireDefault 帮助程序。

JavaScript
import foo from "foo";
import { bar } from "bar";
foo;
bar;

// Is compiled to ...

"use strict";

var _foo = require("foo");
var _bar = require("bar");

_foo.default;
_bar.bar;

loose

boolean,默认为 false

默认情况下,当使用 babel 导出时,会导出一个不可枚举的 __esModule 属性。

JavaScript
var foo = (exports.foo = 5);

Object.defineProperty(exports, "__esModule", {
value: true,
});
注意

考虑迁移到顶级的 enumerableModuleMeta 假设。

babel.config.json
{
"assumptions": {
"enumerableModuleMeta": true
}
}

在不支持此功能的环境中,您可以启用 enumerableModuleMeta 假设,而不是使用 Object.defineProperty,而是使用赋值。

JavaScript
var foo = (exports.foo = 5);
exports.__esModule = true;

strict

boolean,默认为 false

默认情况下,当使用 babel 导出时,会导出一个不可枚举的 __esModule 属性。在某些情况下,此属性用于确定导入默认导出还是包含默认导出。

JavaScript
var foo = (exports.foo = 5);

Object.defineProperty(exports, "__esModule", {
value: true,
});

为了防止导出 __esModule 属性,您可以将 strict 选项设置为 true

lazy

booleanArray<string>(string) => boolean,默认为 false

将 Babel 编译的 import 语句更改为在首次使用其导入的绑定时进行延迟求值。

这可以缩短模块的初始加载时间,因为预先评估依赖项有时是完全不必要的。在实现库模块时尤其如此。

lazy 的值有几种可能的影响

  • false - 不对任何导入的模块进行延迟初始化。

  • true - 不要延迟初始化本地 ./foo 导入,但要延迟初始化 foo 依赖项。

    本地路径更有可能具有循环依赖关系,如果延迟加载可能会中断,因此默认情况下它们不是延迟的,而独立模块之间的依赖关系很少是循环的。

  • Array<string> - 延迟初始化所有与给定字符串之一匹配的源代码导入。

  • (string) => boolean - 传递一个回调函数,该函数将被调用以确定是否应延迟加载给定的源代码字符串。

永远不能延迟导入的两种情况是

  • import "foo";

    副作用导入会自动非延迟,因为它们的存在意味着没有绑定可以稍后启动初始化。

  • export * from "foo"

    重新导出所有名称需要预先执行,因为否则无法知道需要导出哪些名称。

提示

您可以在 此处 阅读有关配置插件选项的更多信息

noInterop

boolean,默认为 false

注意

已弃用:请改用 importInterop 选项。

设置为 true 时,此选项的行为与设置 importInterop: "none" 相同。

相关 assumptions