跳转到主要内容

@babel/plugin-transform-modules-umd

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

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

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

⚠️ 此插件不支持动态导入 (import('./lazy.js'))。

示例

输入

JavaScript
export default 42;

输出

JavaScript
(function(global, factory) {
if (typeof define === "function" && define.amd) {
define(["exports"], factory);
} else if (typeof exports !== "undefined") {
factory(exports);
} else {
var mod = {
exports: {},
};
factory(mod.exports);
global.actual = mod.exports;
}
})(this, function(exports) {
"use strict";

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

exports.default = 42;
});

安装

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

用法

babel.config.json
{
"plugins": ["@babel/plugin-transform-modules-umd"]
}

当此模块在浏览器中运行时,您还可以覆盖特定库的名称。例如,es6-promise 库将自身公开为 global.Promise 而不是 global.es6Promise。这可以通过以下方式解决

babel.config.json
{
"plugins": [
[
"@babel/plugin-transform-modules-umd",
{
"globals": {
"es6-promise": "Promise"
}
}
]
]
}

默认语义

关于默认语义,需要注意以下几点。

*首先*,此转换使用每个导入的 基名 来生成 UMD 输出中的全局名称。这意味着,如果您要导入多个具有相同基名的模块,例如

JavaScript
import fooBar1 from "foo-bar";
import fooBar2 from "./mylib/foo-bar";

它将被转换为对同一个浏览器全局变量的两个引用

JavaScript
factory(global.fooBar, global.fooBar);

如果您将插件选项设置为

JSON
{
"globals": {
"foo-bar": "fooBAR",
"./mylib/foo-bar": "mylib.fooBar"
}
}

它仍然会将两者都转换为一个浏览器全局变量

JavaScript
factory(global.fooBAR, global.fooBAR);

因为转换仍然只使用导入的基名。

*其次*,指定的覆盖仍将传递给 babel-types/src/converters 中的 toIdentifier 函数。这意味着,如果您将覆盖指定为成员表达式,例如

JSON
{
"globals": {
"fizzbuzz": "fizz.buzz"
}
}

这将*不会*转换为 factory(global.fizz.buzz)。相反,它将根据 toIdentifier 中的逻辑转换为 factory(global.fizzBuzz)

*第三*,您不能覆盖导出的全局名称。

使用 exactGlobals: true 实现更灵活的语义

所有这些行为都会限制 globals 映射的灵活性。要消除这些限制,您可以将 exactGlobals 选项设置为 true。这样做会指示插件

  1. 在生成全局名称时始终使用完整的导入字符串,而不是基名
  2. 跳过将 globals 覆盖传递给 toIdentifier 函数。相反,它们将按原样使用,因此如果您不使用有效的标识符或有效的非计算(点)成员表达式,则会出现错误。
  3. 允许通过 globals 映射覆盖导出的全局名称。任何覆盖都必须是有效的标识符或有效的成员表达式。

因此,如果您将 exactGlobals 设置为 true 并且不传递任何覆盖,则第一个示例

JavaScript
import fooBar1 from "foo-bar";
import fooBar2 from "./mylib/foo-bar";

将被转换为

JavaScript
factory(global.fooBar, global.mylibFooBar);

如果您将插件选项设置为

JSON
{
"globals": {
"foo-bar": "fooBAR",
"./mylib/foo-bar": "mylib.fooBar"
},
"exactGlobals": true
}

那么它将被转换为

JavaScript
factory(global.fooBAR, global.mylib.fooBar);

最后,如果将插件选项设置为

babel.config.json
{
"plugins": [
"@babel/plugin-external-helpers",
[
"@babel/plugin-transform-modules-umd",
{
"globals": {
"my/custom/module/name": "My.Custom.Module.Name"
},
"exactGlobals": true
}
]
],
"moduleId": "my/custom/module/name"
}

它将被转换为

JavaScript
factory(mod.exports);
global.My = global.My || {};
global.My.Custom = global.My.Custom || {};
global.My.Custom.Module = global.My.Custom.Module || {};
global.My.Custom.Module.Name = mod.exports;

通过 CLI

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

通过 Node API

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

选项

moduleIds

boolean 默认为 !!moduleId

添加于:v7.9.0

启用模块 ID 生成。

moduleId

字符串

添加于:v7.9.0

要用于模块的硬编码 ID。不能与 getModuleId 一起使用。

getModuleId

(name: string) => string

添加于:v7.9.0

给定 babel 生成的模块名称,返回要使用的名称。返回假值将使用原始的 name

moduleRoot

字符串

添加于:v7.9.0

要包含在生成的模块名称上的根路径。

有关此处未列出的选项,请参阅 @babel/plugin-transform-modules-commonjs 的选项。