Babel
已成为前端工程化开发的必备工具链, 而@babel/preset-env
(babel7.0 以后的插件与预设以@babel为前缀)是常用的一组预先设定的插件,Babel
中文网暂未对该部分内容做翻译, 本文是对Babel
英文官方文档中@babel/preset-env
内容的翻译, 前端小xuo生英语渣渣水平有限, 欢迎指正与交流
@babel/preset-env
@babel/preset-env
是一个智能的babel
预设, 让你能使用最新的JavaScript
语法, 它会帮你转换成代码的目标运行环境支持的语法, 提升你的开发效率并让打包后的代码体积更小
安装
使用npm
npm install --save-dev @babel/preset-env
使用yarn
yarn add @babel/preset-env --dev
运行机制
@babel/preset-env
依赖了一些优秀的开源项目, 如browserslist
, compat-table
, electron-to-chromium
...
我们利用这些数据源维护和增强Babel
语法转换、语法实现, 来支持对应的目标环境的版本的语法、特征
注意
@babel/preset-env
不支持stage-x
的插件
@babel/preset-env
利用你指定的任何目标环境, 检查它们对应的插件并传给Babel
浏览器列表集合
对基于浏览器或者Electron
的项目, 我们推荐使用一个.browserslistrc
文件指定编译目标.如果你已经有了这个配置文件, 它将被很多前段工程化生态的工具利用到, 比如 autoprefixer
, stylelint
, eslint-plugin-compat
...
如果没有配置targets
或者ignoreBrowserslistConfig
, @babel/preset-env
将使用默认的Browserslist
配置
如果你想支持市场份额大于0.25%而且忽略安全更新的浏览器如IE 10
和BlackBerry
的语法转换和语法实现, 你可以采用如下的配置
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry"
}
]
]
}
.browserlistrc
> 0.25%
not dead
或者你可以在package.json
文件里配置
"browserslist": "> 0.25%, not dead"
配置项
如果你想获取更多关于配置项和预设的文档, 可参考preset options
文档
targets
数据类型: string | Array<string> | { [string]: string }
, 默认 {}
描述你的项目支持的目标环境
其可以是一个browserslist-compatible
查询语句
{
"targets": "> 0.25%, not dead"
}
或者是一个描述支持的最小的环境版本的对象
{
"targets": {
"chrome": "58",
"ie": "11"
}
}
环境如: chrome
, opera
, edge
, firefox
, safari
, ie
, ios
, android
, node
, electron
注意, 如果不指定targets
, @babel/prest-env
会将所有的ECMAScript 2015+
代码按照默认的配置去转换
我们不推荐这样使用, 因为这样没有利用到其支持特定浏览器的能力
{
"presets": ["@babel/preset-env"]
}
targets.esmodules
数据类型: boolean
如果你代码运行的浏览器支持ES Modules
(www.ecma-international.org/ecma-262/6.…), 当指定如下的配置, browers
字段将被忽略, 你可以配合<script type="module"></script>
专门为用户提供更小体积的代码文件(jakearchibald.com/2017/es-mod…)
请注意: 如果这样指定
esmodules
编译目标,browsers
字段将被忽略
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"esmodules": true
}
}
]
]
}
targets.node
数据类型: string | "current" | true
如果你的编译针对当前的node
版本, 你可以指定node
配置项, 如果你指定为curren
, 将等同于 "node": process.versions.node
targets.safari
数据类型: string | "tp"
如果你将针对Safari
浏览器的技术预览版technology preview
版本去编译, 可以指定"safari": "tp"
targets.browsers
数据类型: string | Array<string>
一个利用browserlist
的查询选项, 如last 2 versions, > 5%, safari tp
注意, browsers
的结果将被targets
中冲突的项目覆写
注意: 这个配置项将在后期的版本里被移除, 利于只直接设置
targets
成一个查询语句
spec
数据类型: boolean
, 默认为false
为一些允许的但是潜在的会比较慢的插件或者预设做配置
loose
数据类型: boolean
, 默认为false
允许支持loose transformations
的插件或者预设
modules
数据类型: "amd" | "umd" | "systemjs" | "commonjs" | "cjs" | "auto" | false
, 默认为 "auto"
允转换ES6
模块语法为其他的模块类型
设置为false
将不会转换模块
注意cjs
是commonjs
的一个别名
debug
数据类型: boolean
, 默认为false
console.log
输出编译目标或者使用的插件在plugin data version
中指定的版本
include
数据类型: Array<string|RegExp>
, 默认为[]
一个经常包含的插件的数组
合法的配置包括:
Babel plugins
,@babel/plugin-transform-spread
与不带前缀的plugin-transform-spread
都支持- Built-ins(同时支持
cores-js@2
和cores-js@3
, 如es.map
,es.set
, 或者es.object.assign
)
插件的名字可以用完整的或者部分的去指定, 或者使用正则表达式
可以接收的输入:
- 全称(
string
):"es.math.sign"
- 部分名称(
string
):"es.math.*"
(解析为所有以es.math
为前缀的插件) - 正则(
Object
):/^transform-.*$/
或者new RegExp("^transform-modules-.*")
注意以上正则表达式里的.
相当于匹配所有的字符, 不仅仅是.
字符. 而且注意正则表达式里.*
与glob
里*
相反
如果一个原生的实现或者一节结合了不支持的特性加上支持的特性失效时, 这个选项对于debug会很有用
例如, Node 4
支持原生的classes
但是不支持spread
, 如果super
和参数spread
一起使用, @babel/plugin-transform-classes
需要被include
, 不然的话就不可能被转译
注意:
include
和exclude
选项仅在插件被预设包含时才会生效, 所以, 举个例子, 包含@babel/plugin-proposal-do-expressions
, 或者排除@babel/plugin-proposal-function-bind
将会报错, 如果要时候用预设里不包含的插件, 请直接将其添加至plugins
exclude
数据类型: Array<string|RegExp>
, 默认为[]
一个记录不包含或者移除的插件的数组
可能的配置与include
选项类似
这个选项相当于黑名单, 如果你不使用generators
而且当配置useBuiltIns
时不想包含regeneratorRuntime
, 或者利用其它如fast-async
的插件替换Babel's async-to-gen
useBuiltIns
数据类型: "usage" | "entry" | false
, 默认false
这个选项配置了@babel/preset-env
如何处理polyfill
当usage
或者entry
选项被使用, @babel/preset-env
将直接饮用cores-js
模块相当于暴露imports
或者requries
, 这一位置core-js
将被直接解析到文件本身而且需要可访问
因为@babel/polyfill
在Babel 7.4.0
已被废弃, 我们推荐直接添加core-js
和通过corejs
选项设置版本
npm install core-js@3 --save
# or
npm install core-js@2 --save
useBuiltIns: 'entry'
注意: 你的整个app里只能使用一次
import "core-js
和import "regenerator-runtime/runtime"
. 如果你正在使用@babel/polyfill
, 其已包含了core-js
和regenerator-runtime
: 如果多次引入它或报错.多次引入这些包将导致全局的冲突和其它难易追踪的问题. 我们推荐创建一个只包含import
声明的单入口文件
当需要根据不同的基于环境的入口需要引入不同的core-js
时, 这个选项允许一个新的插件来替换import "core-js/stable"
和import "regenerator-runtime/runtime"
声明(或者require("corejs")
和require("regenerator-runtime/runtime")
)
In
import "core-js";
Out(基于不同的环境)
import "core-js/modules/es.string.pad-start";
import "core-js/modules/es.string.pad-end";
引入"core-js"
加载了对于每一个可能的ECMAScript
特性的语法填充, 如果你知道你只需要他们其中的某一部分呢, 当使用core-js@3
和@babel/preset-env
, 能够对每一个core-js
入口和其依赖的优化. 比如, 你看值需要填充数组方法和新的Math
提案:
In
import "core-js/es/array";
import "core-js/proposals/math-extensions";
Out(基于不同的环境)
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
的文档获取关于不同入口的信息
注意: 当使用
core-js@2
(使用corejs: 2
配置项或者隐式使用),@babel/preset-env
将也引入@babel/polyfill
. 这种行为已被废弃, 因为不可能与@babel/polyfill
使用不同的core-js
版本
useBuiltIns: 'usage'
当文件里被使用时, 添加特定的引入来语法填充, 我们利用它, 一个打包的文件只会加载一次相同的语法填充
In
a.js
var a = new Promise();
b.js
var b = new Map();
Out(如果环境需要语法填充)
import "core-js/modules/es.promise";
var a = new Promise();
import "core-js/modules/es.map";
var b = new Map();
Out(如果环境支持该语法)
var a = new Promise();
var b = new Map();
useBuiltIns: false
不在每一个文件自动添加语法填充, 不转换import "core-js"
和import "@babel/polyfill"
为单独的语法填充
corejs
数据结构: 2, 3
或者 { version: 2 | 3, proposals: boolean }
, 默认为 2
这个选项只会在与useBuiltIns: usage
或者useBuiltIns: entry
一起使用时才会生效, 确保@babel/preset-env
为你的core-js
版本注入了正确的引入
默认只有稳定的 ECMAScript
特性的语法填充才被注入, 你有三种方式去做语法填充:
- 当使用
useBuiltIns: "entry"
, 你可直接引入一个proposal polyfill
:import "core-js/proposals/string-replace-all"