Skip to main content

@babel/plugin-transform-modules-umd

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

这个插件包含在 @babel/preset-env 的 modules 选项下

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

🌐 This plugin transforms ES2015 modules to UMD. Note that only the syntax of import/export statements (import "./mod.js") is transformed, as Babel is unaware of different resolution algorithms between implementations of ES2015 modules and UMD.

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

示例​

🌐 Example

在

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;
});

安装​

🌐 Installation

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

用法​

🌐 Usage

🌐 With a configuration file (Recommended)

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

当这个模块在浏览器中运行时,你也可以覆盖特定库的名称。例如,es6-promise 库将自己暴露为 global.Promise 而不是 global.es6Promise。可以通过以下方式来实现:

🌐 You can also override the names of particular libraries when this module is running in the browser. For example the es6-promise library exposes itself as global.Promise rather than global.es6Promise. This can be accommodated by:

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

默认语义​

🌐 Default semantics

关于默认语义有几点需要注意。

🌐 There are a few things to note about the default semantics.

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

🌐 First, this transform uses the basename of each import to generate the global names in the UMD output. This means that if you're importing multiple modules with the same basename, like:

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

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

🌐 it will transpile into two references to the same browser global:

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

如果你将插件选项设置为:

🌐 If you set the plugin options to:

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

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

🌐 it will still transpile both to one browser global:

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

因为再次转换仅使用导入的基本名称。

🌐 because again the transform is only using the basename of the import.

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

🌐 Second, the specified override will still be passed to the toIdentifier function in babel-types/src/converters. This means that if you specify an override as a member expression like:

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

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

🌐 this will not transpile to factory(global.fizz.buzz). Instead, it will transpile to factory(global.fizzBuzz) based on the logic in toIdentifier.

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

🌐 Third, you cannot override the exported global name.

使用 exactGlobals: true 拥有更灵活的语义​

🌐 More flexible semantics with exactGlobals: true

所有这些行为都可能限制 globals 地图的灵活性。要消除这些限制,你可以将 exactGlobals 选项设置为 true。这样做会指示插件去:

🌐 All of these behaviors can limit the flexibility of the globals map. To remove these limitations, you can set the exactGlobals option to true. Doing this instructs the plugin to:

  1. 生成全局名称时,总是使用完整的导入字符串,而不是基本名称
  2. 跳过将 globals 覆盖传递给 toIdentifier 函数。相反,它们会按原样使用,所以如果你不使用有效的标识符或有效的未计算(点)成员表达式,就会出错。
  3. 允许通过 globals 映射覆盖导出的全局名称。任何覆盖再次必须是有效的标识符或有效的成员表达式。

因此,如果你将 exactGlobals 设置为 true 并且没有传入任何覆盖,下面的第一个例子:

🌐 Thus, if you set exactGlobals to true and do not pass any overrides, the first example of:

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

将转换为:

🌐 will transpile to:

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

如果你将插件选项设置为:

🌐 And if you set the plugin options to:

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

然后它将转换为:

🌐 then it'll transpile to:

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

最后,将插件选项设置为:

🌐 Finally, with the plugin options set to:

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"
}

它将转换为:

🌐 it will transpile to:

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​

🌐 Via CLI

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

通过 Node API​

🌐 Via Node API

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

选项​

🌐 Options

allowTopLevelThis​

boolean,默认值为 false。

当这个选项是 true 时,Babel 会将顶层 this(在 ES 模块中总是 undefined)转换为 void 0。

🌐 When this option is true, Babel will transform top level this (always undefined in ES Modules) to void 0.

moduleIds​

boolean 默认为 !!moduleId

已添加于:v7.9.0

🌐 Added in: v7.9.0

启用模块 ID 生成。

🌐 Enables module ID generation.

moduleId​

string

已添加于:v7.9.0

🌐 Added in: v7.9.0

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

🌐 A hard-coded ID to use for the module. Cannot be used alongside getModuleId.

getModuleId​

(name: string) => string

已添加于:v7.9.0

🌐 Added in: v7.9.0

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

🌐 Given the babel-generated module name, return the name to use. Returning a falsy value will use the original name.

moduleRoot​

string

已添加于:v7.9.0

🌐 Added in: v7.9.0

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

🌐 A root path to include on generated module names.

对于这里没有列出的选项,请查看 @babel/plugin-transform-modules-commonjs 的选项。

🌐 For options not listed here, see options for @babel/plugin-transform-modules-commonjs.