@babel/preset-env
@babel/preset-envopen in new window是一个灵活的预设,你可以无需管理目标环境需要的语法转换或浏览器polyfill
,就可以使用最新的 JavaScript。这将让你的生活更简单,也会让 JavaScript 打包文件更小。
安装
# with npm
npm install --save-dev @babel/preset-env
2
# with yarn
yarn add @babel/preset-env --dev
2
它如何工作
@babel/preset-env
是基于一些优秀的开源项目,比如browserslistopen in new window、compat-tableopen in new window、electron-to-chromiumopen in new window,要是没有它们,也就没有@babel/preset-env
。
我们利用这些数据源来维护一些映射表:
- 我们支持的设备环境的哪个版本需要获得哪些 JavaScript 语法或浏览器特性的支持的映射
- 这些语法和特性到 Babel 转换插件和
core-js
的polyfill
的映射
注意
尤其需要注意的是,@babel/preset-env
不支持stage-x
的插件。
@babel/preset-env
拿到你指定的目标环境,检查这些映射表来编译一系列的插件并传给 Babel。
Browserslist 集成
针对基于浏览器的或Electron-based
的项目,我们推荐使用.browserslistrcopen in new window文件来指定目标环境。你可能已经有了这个配置文件,因为它会被生态系统里的许多工具用到,比如autoprefixeropen in new window、stylelintopen in new window、eslint-plugin-compatopen in new window等等。
若是没设置targets
或ignoreBrowserslistConfig
配置项,@babel/preset-env
默认会使用browserslist config sourcesopen in new window。
比如,仅仅包含>0.25%
市场份额浏览器的那些polyfill
和代码转换:
Options:
{
"presets": [
[
"@babel/preset-env",
{
// 原文档是这样的
// "useBuiltIns": "entry",
// 实际上应该是这样
"targets": "> 0.25%, not dead"
}
]
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
browserslist:
> 0.25%
not dead
2
或package.json
:
{
"browserslist": "> 0.25%, not dead"
}
2
3
Options
关于更多设置预设的配置项,可参考preset optionsopen in new window文档。
targets
string | Array<string> | { [string]: string }
,默认为{}
。
描述你项目支持的目标环境。
这可以使用browserslist-compatibleopen in new window形式的query
:
{
"targets": "> 0.25%, not dead"
}
2
3
或者支持的最小环境版本的对象:
{
"targets": {
"chrome": "58",
"ie": "11"
}
}
2
3
4
5
6
这些环境可以是:
chrome
opera
edge
firefox
safari
ie
ios
android
node
electron
若是没有指定环境,@babel/preset-env
默认将转换所有的 ECMAScript 2015+ 代码。
{
"presets": ["@babel/preset-env"]
}
2
3
注意
我们不推荐使用preset-env
时不指定环境,因为这样就无法发挥它指定目标浏览器能力的优势。
targets.esmodules
boolean
你要支持的目标浏览器可能支持ES 模块open in new window。当指定该选项,指定的目标浏览器将被忽略。你可以结合<script type="module"></script>
来使用这样方式,这样就会产生更小的脚本文件(https://jakearchibald.com/2017/es-modules-in-browsers/#nomodule-for-backwards-compatibilityopen in new window)。
注意
请注意,当指定esmodules
后,将忽略浏览器目标环境。
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"esmodules": true
}
}
]
]
}
2
3
4
5
6
7
8
9
10
11
12
targets.node
string | "current" | true
若是你想要针对当前node
版本编译,你可以指定"node": true
或"node": "current"
,这与"node": process.versions.node
是一样的。
targets.safari
string | "tp"
若是你想要针对 Safari 的 technology preview 版本编译,你可以指定"safari": "tp"
。
targets.browsers
即将在下个版本移除。
spec
boolean
, 默认为false
。
Enable more spec compliant, but potentially slower, transformations for any plugins in this preset that support them.
loose
boolean
, 默认为false
。
开启"loose" transformationsopen in new window,针对预设里允许loose
转换的任何插件。
modules
"amd" | "umd" | "systemjs" | "commonjs" | "cjs" | "auto" | false
,默认为"auto"
。
Enable transformation of ES6 module syntax to another module type.
开启将 ES6 模块语法转换为其他模块语法。设置为false
将不转换模块。
cjs
是commonjs
的别名。
debug
boolean
, 默认为false
。
将使用的插件/目标环境以及plugin data versionopen in new window指定的版本输入到console.log
。
include
Array<string|RegExp>
, 默认为[]
。
插件数组,这些插件总是被使用(即使目标环境不需要)。
有效的选项包括:
- Babel 插件,带前缀或不带前缀都支持,比如
@babel/plugin-transform-spread
或plugin-transform-spread
。 - 内置对象,比如
es6.map
、es6.set
、或es6.object.assign
。
插件名称可以全部或部分指定(或使用正则表达式)。
可接受的输入有:
- 全部名称,
string
:"es6.math.sign"
- 部分名称,
string
:"es6.math.*"
(解析为所有以es6.math
为前缀的插件) RegExp
对象:/^transform-.*$/
或new RegExp("^transform-modules-.*")
注意,上面的.
是RegExp
的一部分,等同于任何字符,而不是实际的字符.
。另外注意在RegExp
里使用.*
匹配任何字符,类似于glob
格式里的*
。
若是原生实现里有bug
,或者只实现了特性的一部分时,这个配置项将尤其有用。
比如,Node 4 支持原生的类但是不支持函数参数的扩展运算符。若是调用super
时使用扩展运算符,则需要引入@babel/plugin-transform-classes
进行转换。
注意
注意,include
和exclude
选项仅能作用于包含在预设里的插件。因此,若是使用include
包含@babel/plugin-proposal-do-expressions
插件或是使用exclude
排除@babel/plugin-proposal-function-bind
,都会抛错。若是想使用不包含在预设里的插件,可以直接添加在plugins
里。
exclude
Array<string|RegExp>
,默认为[]
。
插件数组,这些插件将不会被使用(即使目标环境需要)。
可能的选项与include
相同。
该选项设置了一个转换插件的黑名单,比如不使用@babel/plugin-transform-regenerator
,若是你不使用生成器函数generators
以及不想包含regeneratorRuntime
(当使用useBuiltIns
时)或使用另一个插件比如fast-asyncopen in new window而不是Babel 的async-to-gen
open in new window。
useBuiltIns
"usage"
| "entry"
| false
,默认是false
。
注意
该选项会直接添加对core-js
模块的引用。因此core-js
将相对于文件自身进行解析,这要求core-js
是可访问的。在你的项目,若是没有core-js
依赖或是有多个版本,你可能需要指定core-js@2
作为顶级依赖。
这选项配置@babel/preset-env
如何处理polyfill
。
useBuiltIns: 'entry'
注意
整个项目里能且仅能有一次使用require("@babel/polyfill");
。多次引入@babel/polyfill
将抛错,因为这将导致全局冲突以及其他难以追踪的问题。我们推荐创建一个单独的入口你文件,仅仅包含require
语句。
该选项启用一个新的插件,该插件将基于你环境单独引入core-js
的各个文件,以此来替换掉import "@babel/polyfill"
或require("@babel/polyfill")
语句。
npm install @babel/polyfill --save
输入:
import "@babel/polyfill";
输出(基于环境而不同):
import "core-js/modules/es7.string.pad-start";
import "core-js/modules/es7.string.pad-end";
2
这对直接引入core-js
也是有效的(import "core-js";
或require('core-js');
)。
useBuiltIns: 'usage'(实验性的)
添加对每个文件中使用的特定的polyfill
的引入。我们利用了“一个打包文件将只加载一次相同的polyfill
”这一事实。
输入:
// a.js
var a = new Promise();
2
// b.js
var b = new Map();
2
输出(若是环境不支持):
import "core-js/modules/es6.promise";
var a = new Promise();
2
import "core-js/modules/es6.map";
var b = new Map();
2
输出(若是环境支持):
var a = new Promise();
var b = new Map();
useBuiltIns: false
每个文件里不自动添加polyfill
,或不将import "@babel/polyfill"
转换为单独的polyfill
。
forceAllTransforms
boolean
,默认为false
。
有了 Babel 7 的Javascipt config fileopen in new window支持,若是env
被设置为product
,你可以强制使用所有的转换。
module.exports = function(api) {
return {
presets: [
[
"@babel/preset-env",
{
targets: {
chrome: 59,
edge: 13,
firefox: 50,
},
// for uglifyjs...
forceAllTransforms: api.env("production"),
},
],
],
};
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
注意
targets.uglify
已经废弃并将在下个主版本移除。
默认情况下,这个预设将会按需运行目标环境需要的所有转换。若是你想要运行所有的转换(而忽略目标环境是否需要),则需要开启该选项,这对于输出代码在 UglifyJS 上或仅支持 ES5 的环境上运行来说将是非常有用的。
注意
Uglify 有一个在建的"Harmony"分支来设法解决 ES6 支持缺失的问题,但是这还不太稳定。你可以在UglifyJS2 issue #448open in new window关注这个进度。如果你想要一个支持 ES6 语法的可选的压缩工具,我们推荐使用babel-minifyopen in new window
configPath
string
,默认为process.cwd()
。
搜索 Browserslist 配置的开始点,会基于此开始点向上搜索到系统根目录,直到发现配置文件。
ignoreBrowserslistConfig
boolean
,默认为false
。
切换是否使用browserslist config sourcesopen in new window,这将决定是否要搜索任何的 Browserslist 配置文件或package.json
里的browserslist
选项。当项目里存在 Browserslist 配置文件但是不用于 Babel 编译时,这将非常有用。
shippedProposals
切换是否开启对处于提案中的且浏览器已经实现的内置对象/特性的支持。若是你的目标环境已经有了对某提案特性的原生支持,将开启与其相匹配的解析器语法插件,而不是执行任何的转换。注意,这不会开启与@babel/preset-stage-3open in new window相同的转换,因为这些提案在正式落地到浏览器之前还会继续改变。
当前以下内容是支持的:
Builtins
Features
- None
@vue/babel-preset-env
@vue/babel-preset-envopen in new window是针对 Vue.js 项目,基于@babel/preset-env
、@vue/babel-preset-jsx
、@babel/plugin-transform-runtime
等等预设和插件的封装,主要包含了以下内容:
- @babel/preset-envopen in new window:主要使用该预设,并基于用户输入和目标环境等对参数进行了处理。
polyfills
@vue/babel-preset-env
里默认包含了以下polyfill
,详见源码open in new window,但是这些polyfill
会根据目标环境来确定最终是否会传入@babel/preset-env
预设里。假设目标环境都实现了这些内置对象或特性,则最终不会包含这些polyfill
。详见源码open in new window。es6.array.iterator
es6.promise
es6.object.assign
es7.promise.finally
- @babel/plugin-transform-runtimeopen in new window:仅使用了该插件引入模块化的
helpers
替换内联的 Babelhelpers
。 @babel/plugin-syntax-dynamic-import
@babel/plugin-proposal-decorators
@babel/plugin-proposal-class-properties
- 等等