@babel/plugin-transform-modules-commonjs
历史
版本 | 变更 |
---|---|
v7.14.0 | 实现了 importInterop 选项 |
此插件包含在 @babel/preset-env
的 modules
选项下
此插件将 ECMAScript 模块转换为 CommonJS。请注意,只有导入/导出语句(import "./mod.js"
)和导入表达式(import('./mod.js')
)的语法会被转换,因为 Babel 不知道 ECMAScript 模块和 CommonJS 实现之间不同的解析算法。
示例
输入
export default 42;
输出
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = 42;
安装
- npm
- Yarn
- pnpm
npm install --save-dev @babel/plugin-transform-modules-commonjs
yarn add --dev @babel/plugin-transform-modules-commonjs
pnpm add --save-dev @babel/plugin-transform-modules-commonjs
用法
使用配置文件(推荐)
// without options
{
"plugins": ["@babel/plugin-transform-modules-commonjs"]
}
// with options
{
"plugins": [
["@babel/plugin-transform-modules-commonjs", {
"allowTopLevelThis": true
}]
]
}
通过 CLI
babel --plugins @babel/plugin-transform-modules-commonjs script.js
通过 Node API
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
属性。然后,使用此属性来确定导入是默认导出还是包含默认导出。
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
的值。
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
帮助程序。
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
属性。
var foo = (exports.foo = 5);
Object.defineProperty(exports, "__esModule", {
value: true,
});
考虑迁移到顶级的 enumerableModuleMeta
假设。
{
"assumptions": {
"enumerableModuleMeta": true
}
}
在不支持此功能的环境中,您可以启用 enumerableModuleMeta
假设,而不是使用 Object.defineProperty
,而是使用赋值。
var foo = (exports.foo = 5);
exports.__esModule = true;
strict
boolean
,默认为 false
默认情况下,当使用 babel 导出时,会导出一个不可枚举的 __esModule
属性。在某些情况下,此属性用于确定导入是默认导出还是包含默认导出。
var foo = (exports.foo = 5);
Object.defineProperty(exports, "__esModule", {
value: true,
});
为了防止导出 __esModule
属性,您可以将 strict
选项设置为 true
。
lazy
boolean
、Array<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"
相同。