@babel/preset-env
@babel/preset-env 是一个智能预设,让你可以使用最新的 JavaScript,而不需要精细管理目标环境所需的语法转换(以及可选的浏览器 polyfill)。这既让你的开发更轻松,也让 JavaScript 打包更小!
安装
🌐 Install
- npm
- Yarn
- pnpm
- Bun
npm install --save-dev @babel/preset-env
yarn add --dev @babel/preset-env
pnpm add --save-dev @babel/preset-env
bun add --dev @babel/preset-env
它是如何工作的?
🌐 How Does it Work?
@babel/preset-env 不可能实现,如果没有一些很棒的开源项目,比如 browserslist、compat-table 和 electron-to-chromium。
我们利用这些数据源来维护我们支持的目标环境中哪个版本获得了 JavaScript 语法或浏览器特性的映射,以及将这些语法和特性映射到 Babel 转换插件和 core-js 补丁的映射。
🌐 We leverage these data sources to maintain mappings of which version of our supported target environments gained support of a JavaScript syntax or browser feature, as well as a mapping of those syntaxes and features to Babel transform plugins and core-js polyfills.
@babel/preset-env 不会包含任何低于第 3 阶段的 JavaScript 语法提案,因为在 TC39 流程的那个阶段,反正也没有浏览器会实现它们。那些需要手动添加。shippedProposals 选项会包含一些浏览器已经实现的第 3 阶段提案。
@babel/preset-env 会获取你指定的任何 目标环境,并根据它的映射进行检查,从而编译出一个插件列表并传递给 Babel。
浏览器列表集成
🌐 Browserslist Integration
对于基于浏览器或 Electron 的项目,我们建议使用 .browserslistrc 文件来指定目标。你可能已经有这个配置文件,因为它被生态系统中的许多工具使用,比如 autoprefixer、stylelint、eslint-plugin-compat 等。
🌐 For browser- or Electron-based projects, we recommend using a .browserslistrc file to specify targets. You may already have this configuration file as it is used by many tools in the ecosystem, like autoprefixer, stylelint, eslint-plugin-compat and many others.
默认情况下,@babel/preset-env 会使用 browserslist 配置来源,除非设置了 targets 或 ignoreBrowserslistConfig 选项。
🌐 By default @babel/preset-env will use browserslist config sources unless either the targets or ignoreBrowserslistConfig options are set.
如果你依赖 browserslist 的默认查询(无论是明确指定的,还是因为没有 browserslist 配置),你会想查看 No targets 部分,以了解 preset-env 的行为。
例如,仅包含浏览器市场份额 >0.25% 的用户所需的填充和代码转换(忽略没有安全更新的浏览器,如 IE 10 和 BlackBerry):
🌐 For example, to only include polyfills and code transforms needed for users whose browsers have >0.25% market share (ignoring browsers without security updates like IE 10 and BlackBerry):
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry",
"corejs": "3.22"
}
]
]
}
> 0.25%
not dead
or
{ "browserslist": "> 0.25%, not dead" }
请注意,自从 v7.4.5 起,browserslist 查询是通过 mobileToDesktop: true 解析的。例如,如果你想创建一个查询快照,可以运行 npx browserslist --mobile-to-desktop ">0.25%, not dead"。
选项
🌐 Options
要了解更多关于为预设设置选项的信息,请参考preset options文档。
🌐 For more information on setting options for a preset, refer to the preset options documentation.
targets
string | Array<string> | { [string]: string },如果在 @babel/preset-env 的文档中没有指定任何与 browserslist 相关的选项,则默认为顶层的 targets 选项,否则默认为 {}。
使用方法请参考targets选项文档。
🌐 For usage, refer to the targets option documentation.
bugfixes
在 Babel 8 中,这个选项已经被移除了。@babel/preset-env 将始终把有问题的语法编译成你的目标浏览器支持的最接近的非破坏性现代语法。
🌐 This option has been removed in Babel 8. @babel/preset-env will always compile the broken syntax to the closest non-broken modern syntax supported by your target browsers.
loose,spec
🌐 loose, spec
这些选项在 Babel 8 中已被移除。建议迁移到自 Babel 7.13 起可用的顶层 assumptions。有关基于假设的等效配置,请参阅[“从 @babel/preset-env 的 "loose" 和 "spec" 模式迁移](assumptions.md#migrating-from-babelpreset-envs-loose-and-spec-modes),可以直接复制粘贴作为起点。
modules
"amd" | "umd" | "systemjs" | "commonjs" | "cjs" | "auto" | false,默认值为 "auto"。
启用将 ES 模块语法转换为另一种模块类型。注意,cjs 只是 commonjs 的别名。
🌐 Enable transformation of ES module syntax to another module type. Note that cjs is just an alias for commonjs.
将此设置为 false 将保留 ES 模块。只有在打算向浏览器发布原生 ES 模块时才使用。如果你使用带有 Babel 的打包工具,默认的 modules: "auto" 总是更好。
🌐 Setting this to false will preserve ES modules. Use this only if you intend to ship native ES Modules to browsers. If you are using a bundler with Babel, the default modules: "auto" is always preferred.
modules: "auto"
默认情况下,@babel/preset-env 使用 caller 数据来确定是否应该转换 ES 模块和模块特性(例如 import())。通常,caller 数据会在打包工具插件中指定(例如 babel-loader、@rollup/plugin-babel),因此不建议你自己传递 caller 数据——传入的 caller 可能会覆盖打包工具插件中的设置,将来如果打包工具支持新的模块特性,你可能会得到次优结果。
🌐 By default @babel/preset-env uses caller data to determine whether ES modules and module features (e.g. import()) should be transformed. Generally caller data will be specified in the bundler plugins (e.g. babel-loader, @rollup/plugin-babel) and thus it is not recommended to pass caller data yourself -- The passed caller may overwrite the one from bundler plugins and in the future you may get suboptimal results if bundlers supports new module features.
除非调用者另有说明,Babel 会默认它支持 ES 模块语法,包括 import、import() 和 import * as ns。
🌐 Unless the caller specifies otherwise, Babel will assume that it does support ES modules syntax including import, import() and import * as ns.
debug
boolean,默认值为 false。
将由 preset-env 启用的 polyfills 和转换插件输出到 console.log,并且(如果适用)显示哪些目标需要它。
🌐 Outputs to console.log the polyfills and transform plugins enabled by preset-env and, if applicable, which one of your targets that needed it.
include
Array<string|RegExp>,默认值为 []。
历史
| 版本 | 变更 |
|---|---|
v7.4.0 | 支持注入 core-js@3 填充 |
始终包含的插件数组。
🌐 An array of plugins to always include.
有效选项包括:
🌐 Valid options include any:
- Babel 插件 - 支持完整名称和简写名称,例如下面的用法在功能上是等效的:
@babel/plugin-transform-optional-chaining@babel/transform-optional-chainingtransform-optional-chaining
- core-js@3 的 polyfills,比如
es.map、es.set或es.object.assign。
插件名称可以完全或部分指定(或者使用 RegExp)。
🌐 Plugin names can be fully or partially specified (or using RegExp).
可接受的输入:
🌐 Acceptable inputs:
- 全名(
string):"es.math.sign" - 部分名称(
string):"es.math.*"(解析为所有以es.math前缀开头的插件) RegExp对象:/^transform-.*$/或new RegExp("^transform-modules-.*")
请注意,上面的 . 是 RegExp 对应用来匹配任何字符的,而不是实际的 '.' 字符。还要注意,要匹配任意字符,在 RegExp 中使用的是 .*,而不是 glob 格式中的 *。
🌐 Note that the above . is the RegExp equivalent to match any character, and not the actual '.' character. Also note that to match any character .* is used in RegExp as opposed to * in glob format.
如果原生实现中存在错误,或者不支持的功能 + 支持的功能的组合不起作用,则此选项很有用。
🌐 This option is useful if there is a bug in a native implementation, or a combination of a non-supported feature + a supported one doesn't work.
例如,Node 4 支持原生类,但不支持扩展操作符。如果在 super 中使用了扩展参数,那么 @babel/plugin-transform-classes 转换需要被 include,因为否则无法用 super 转译扩展操作符。
🌐 For example, Node 4 supports native classes but not spread. If super is used with a spread argument, then the @babel/plugin-transform-classes transform needs to be included, as it is not possible to transpile a spread with super otherwise.
exclude
Array<string|RegExp>,默认值为 []。
始终排除/删除的插件数组。
🌐 An array of plugins to always exclude/remove.
可能的选项和 include 选项一样。
🌐 The possible options are the same as the include option.
这个选项对于排除像 @babel/plugin-transform-regenerator 这样的转换很有用,例如,如果你使用的是其他插件,比如 fast-async,而不是 Babel 的 async-to-gen 时。
🌐 This option is useful for excluding a transform like @babel/plugin-transform-regenerator, for example if you are using another plugin like fast-async instead of Babel's async-to-gen.
useBuiltIns, corejs
在 Babel 8 中,这个选项已经被移除了。要注入 polyfill,你可以直接使用 babel-plugin-polyfill-corejs3。
🌐 This option has been removed in Babel 8. To inject polyfills, you can use babel-plugin-polyfill-corejs3 directly.
useBuiltIns: 'entry'
历史
| 版本 | 变更 |
|---|---|
v7.4.0 | 它替换了 "core-js/stable" 和 "regenerator-runtime/runtime" 的条目导入 |
v7.0.0 | 它替换了 "@babel/polyfill" 的条目导入 |
Only use import "core-js"; once in your whole app.
多次导入或引用这些包可能会导致全局冲突和其他难以追踪的问题。我们建议创建一个只包含 import 语句的单一入口文件。
🌐 Multiple imports or requires of those packages might cause global collisions and other issues that are hard to trace.
We recommend creating a single entry file that only contains the import statements.
这个选项启用一个新插件,根据环境将 import "core-js/stable"; 和 require("core-js"); 语句替换为分别导入不同 core-js 入口点。
🌐 This option enables a new plugin that replaces the import "core-js/stable"; and require("core-js"); statements with individual imports to different core-js entry points based on environment.
在
import "core-js";
输出(根据环境不同而不同)
import "core-js/modules/es.string.pad-start";
import "core-js/modules/es.string.pad-end";
导入 "core-js" 会为每一个可能的 ECMAScript 特性加载 polyfill:如果你只需要其中的一部分怎么办?使用 core-js@3 时,@babel/preset-env 能够优化每一个 core-js 入口点及其组合。例如,你可能只想为数组方法和新的 Math 提案加 polyfill:
🌐 Importing "core-js" loads polyfills for every possible ECMAScript feature: what if you know that you only need some of them? When using core-js@3, @babel/preset-env is able to optimize every single core-js entrypoint and their combinations. For example, you might want to only polyfill array methods and new Math proposals:
在
import "core-js/es/array";
import "core-js/proposals/math-extensions";
输出(根据环境不同而不同)
import "core-js/modules/es.array.unscopables.flat";
import "core-js/modules/es.array.unscopables.flat-map";
import "core-js/modules/esnext.math.clamp";
import "core-js/modules/esnext.math.deg-per-rad";
import "core-js/modules/esnext.math.degrees";
import "core-js/modules/esnext.math.fscale";
import "core-js/modules/esnext.math.rad-per-deg";
import "core-js/modules/esnext.math.radians";
import "core-js/modules/esnext.math.scale";
你可以阅读 core-js 的文档,以了解有关不同入口点的更多信息。
🌐 You can read core-js's documentation for more information about the different entry points.
useBuiltIns: 'usage'
在每个文件使用到 polyfill 时,会添加特定的导入。我们利用了打包工具只会加载同一个 polyfill 一次的特性。
🌐 Adds specific imports for polyfills when they are used in each file. We take advantage of the fact that a bundler will load the same polyfill only once.
在
var a = new Promise();
var b = new Map();
输出(如果环境不支持的话)
import "core-js/modules/es.promise";
var a = new Promise();
import "core-js/modules/es.map";
var b = new Map();
输出(如果环境支持)
var a = new Promise();
var b = new Map();
useBuiltIns: false
不要自动为每个文件添加 polyfill,也不要把 import "core-js" 或 import "@babel/polyfill" 转换成单独的 polyfill。
🌐 Don't add polyfills automatically per file, and don't transform import "core-js" or import "@babel/polyfill" to individual polyfills.
corejs
已添加于:v7.4.0
🌐 Added in: v7.4.0
string 或 { version: string, proposals: boolean },默认是 "3.0"。version 字符串可以是任意支持的 core-js 版本,带有小版本号。例如:"3.33"。
这个选项只有在与 useBuiltIns: usage 或 useBuiltIns: entry 一起使用时才会生效,并确保 @babel/preset-env 注入你的 core-js 版本支持的 polyfill。
🌐 This option only has an effect when used alongside useBuiltIns: usage or useBuiltIns: entry, and ensures @babel/preset-env injects the polyfills supported by your core-js version.
默认情况下,只会注入稳定 ECMAScript 功能的 polyfill:如果你想为提案添加 polyfill,你有三种不同的选择:
🌐 By default, only polyfills for stable ECMAScript features are injected: if you want to polyfill proposals, you have three different options:
- 使用
useBuiltIns: "entry"时,你可以直接导入一个 提案 polyfill:import "core-js/proposals/string-replace-all"。 - 使用
useBuiltIns: "usage"时,你有两种不同的选择:- 将
shippedProposals选项设置为true。这将为已经在浏览器中使用了一段时间的提案启用 polyfill 和转换。 - 使用
corejs: { version: "3.8", proposals: true }。这将启用core-js@3.8支持的每个提案的填充。
- 将
forceAllTransforms
boolean,默认值为 false。
示例
有了 Babel 7 的 JavaScript 配置文件 支持,如果 env 设置为 production,你可以强制运行所有转换。
🌐 With Babel 7's JavaScript config file support, you can force all transforms to be run if env is set to production.
module.exports = function(api) {
return {
presets: [
[
"@babel/preset-env",
{
targets: {
chrome: 59,
edge: 13,
firefox: 50,
},
// for uglifyjs...
forceAllTransforms: api.env("production"),
},
],
],
};
};
targets.uglify 已不再推荐使用,并将在下一个大版本中被移除,建议使用这个替代。
默认情况下,这个预设会运行目标环境所需的所有转换。如果你想强制运行_所有_转换,可以启用这个选项,这在输出会经过 UglifyJS 或者只支持 ES5 的环境时非常有用。
🌐 By default, this preset will run all the transforms needed for the targeted environment(s). Enable this option if you want to force running all transforms, which is useful if the output will be run through UglifyJS or an environment that only supports ES5.
如果你需要一个 确实 支持 ES6 语法的替代压缩器,我们推荐 Terser。
configPath
string,默认值为 process.cwd()
browserslist 的配置搜索将开始的起点,并上升到系统根目录,直到找到。
🌐 The starting point where the config search for browserslist will start, and ascend to the system root until found.
ignoreBrowserslistConfig
boolean,默认值为 false
切换是否使用 browserslist 配置来源,这包括搜索任何 browserslist 文件或引用 package.json 中的 browserslist 键。对于那些使用 browserslist 配置但文件不会被 Babel 编译的项目,这非常有用。
🌐 Toggles whether or not browserslist config sources are used, which includes searching for any browserslist files or referencing the browserslist key inside package.json. This is useful for projects that use a browserslist config for files that won't be compiled with Babel.
browserslistEnv
新增于:v7.10.0
string,默认值为 undefined
🌐 Added in: v7.10.0
string, defaults to undefined
要使用的 Browserslist 环境。
🌐 The Browserslist environment to use.
shippedProposals
boolean,默认值为 false
历史
| 版本 | 变更 |
|---|---|
v7.14.0 | 包含私有字段品牌检查 |
v7.12.0 | 包含类静态块和导入断言 |
v7.10.0 | 包含类属性和私有方法 |
v7.9.0 | 包含数字分隔符 |
切换以启用对浏览器中已发布的内置/功能提案的支持。如果你的目标环境已原生支持某个功能提案,那么会启用匹配的解析器语法插件,而不是执行任何转换。注意,这并不等同于启用 @babel/preset-stage-3 的相同转换,因为提案在落地到浏览器之前可能会继续变化。
🌐 Toggles enabling support for builtin/feature proposals that have shipped in browsers. If your target environments have native support for a feature proposal, its matching parser syntax plugin is enabled instead of performing any transform. Note that this does not enable the same transformations as @babel/preset-stage-3, since proposals can continue to change before landing in browsers.
当前支持以下内容:
🌐 The following are currently supported:
使用 useBuiltIns: "usage" 时注入的 内置函数
- esnext.global-this(仅受
core-js@3支持) - esnext.string.match-all(仅
core-js@3支持)
特点
- 导入属性(仅解析)
具体化功能
这些功能在旧版本的 Babel 中由 shippedProposals 标志控制。现在它们已普遍可用。
你可以在这里阅读更多关于配置预设选项的信息
注意事项
🌐 Caveats
无效的浏览器列表查询
🌐 Ineffective browserslist queries
虽然 op_mini all 是有效的 browserslist 查询,但 preset-env 目前忽略它,因为 缺少支持数据 针对 Opera Mini。
🌐 While op_mini all is a valid browserslist query, preset-env currently ignores it due to lack of support data for Opera Mini.