# babel - preset-env和polyfill
@babel/preset-env + @babel/polyfill 可以完全实现 ES 基础语法的转译 + 新 API 的转译,让低端运行环境(浏览器和node)能够识别和运行较新的语法规范(ES6/ES7/ES8/ES99)。
# @babel/preset-env
主要完成基本语法转义。或者说语法糖:箭头函数,async
在之前,需要使用 preset-es20**
系列的 babel 预设,所以有个问题就是,每增加一个新的提案,就需要加一个。。现在只用一个就可以了。
Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转码。
- 安装
yarn add @babel/preset-env -D
- 添加配置
{
"presets": [
[
"@babel/preset-env",
{
"modules": false
}
]
],
"plugins": []
}
2
3
4
5
6
7
8
9
10
11
modules:false 对ES6的模块文件不做转化,以便使用tree shaking、sideEffects等
# @babel/polyfill
主要完成新增 API 的转义。
本质上 @babel/polyfill 是 core-js 库的别名。core-js@3 之后,需要使用 core-js + regenerator-runtime 的方式来引入了。
- 安装
yarn add @babel/polyfill
- 添加配置
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry",
"modules": false,
"corejs": 2
}
]
]
}
2
3
4
5
6
7
8
9
10
11
12
"corejs": 2 新版本的@babel/polyfill包含了 core-js@2 和 core-js@3 版本,所以需要声明版本,否则webpack运行时会报warning,此处暂时使用core-js@2版本
- 配置参数
- modules:
"amd" | "umd" | "systemjs" | "commonjs" | "cjs" | "auto" | false
,默认值是 auto。
用来转换 ES6 的模块语法。如果使用 false,将不会对文件的模块语法进行转化。
如果要使用 webpack 中的一些新特性,比如 tree shaking 和 sideEffects,就需要设置为 false,对 ES6 的模块文件不做转化,因为这些特性只对 ES6 的模块有效。 - useBuiltIns:
"usage" | "entry" | false
,默认值是 false。
- false:需要在 js 代码第一行主动 import '@babel/polyfill',会将@babel/polyfill 整个包全部导入。
(能覆盖到所有 API 的转译,打包后体积最大) - entry:需要在 js 代码第一行主动 import '@babel/polyfill',会将 browserslist 环境不支持的所有垫片都导入。
(能够覆盖到'hello'.includes('h')
这种句法(待验证),足够安全,代码体积不是特别大) - usage:项目里不用主动 import,会自动将代码里已使用到的、且 browserslist 环境不支持的垫片导入。
(检测不到'hello'.includes('h')
这种句法,对这类原型链上的句法问题不会做转译,书写代码需注意,体积最小)
- false:需要在 js 代码第一行主动 import '@babel/polyfill',会将@babel/polyfill 整个包全部导入。
- targets:用来配置需要支持的的环境,不仅支持浏览器,还支持 node。如果没有配置 targets 选项,就会读取项目中的 browserslist 配置项。
- loose:默认 false,babel 输出模式,宽松模式下,输出代码更像手写的(大概少了很多类型兼容判断)。如果 preset-env 中包含的 plugin 支持 loose 的设置,那么可以通过这个字段来做统一的设置。
- modules:
使用 @babel/polyfill
的方式,会在全局挂载新 API,会污染全局命名空间,不推荐在工具库中使用这种方式。
# corejs@3
替换 @babel/polyfill 方案。
原因:
babel-loader > 8.0.0 @babel/core > 7.4.0
- 安装依赖
yarn add babel-loader @babel/core @babel/preset-env -D
yarn add core-js regenerator-runtime
2
- .babelrc 配置
{
"presets": [
[
"@babel/preset-env",
{
"modules": false,
"useBuiltIns": "entry",
"corejs": {
"version": 3,
"proposals": true
}
}
]
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 引入依赖
根据 useBuiltIns
的选择来若修改。参考上面 @babel/polyfill 配置参数的介绍。
在代码头部入口(app.js
),做修改:
import 'core-js/stable'
import 'regenerator-runtime/runtime'
2
core-js@3废弃了 @babel/polyfill ,实现了完全无污染的API转译,但是其暂时会增加打包体积。
# @babel/plugin-transform-runtime
按需加载 API 转义。
特点是:不会污染原型链。适用于在开发第三方 js 库时使用。
- 安装依赖
yarn add babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
yarn add @babel/runtime-corejs3
2
- .babelrc 文件配置
{
"presets": [
[
"@babel/preset-env",
{
"modules": false
}
]
],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": {
"version": 3,
"proposals": true
},
"useESModules": true
}
]
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- 配置参数
corejs
:false | 2 | 3 | { version: 2 | 3, proposals: boolean }
,默认是false
;使用corejs:3
的时候,可以设置proposals: true
来启用 polyfill 提案。version
决定了runtime
的版本;
corejs | Install command | 效果 |
---|---|---|
false | npm install --save @babel/runtime | 辅助语法转换 |
2 | npm install --save @babel/runtime-corejs2 | 语法转换,无污染的 API 转译,不支持实例方法 |
3 | npm install --save @babel/runtime-corejs3 | 语法转换,无污染的 API 转译,支持实例方法,增删了功能 |
helpers
默认值 true,用来开启是否使用 helper 函数来重写语法转换的函数。useESModules
默认值 false,是否对文件使用 ES 的模块语法,使用 ES 的模块语法可以减少文件的大小。
- transform-runtime 使用 core-js@3
- 在之前的版本中,无法模拟实例上的方法,比如数组的 includes 方法就无法被 polyfill,只能完整加载才可以。在 core-js@3 的版本中,所有的实例方法都可以被 polyfill 了。
- 不污染原型,使用沙盒(sandbox)模式引入。
- 支持对 ECMAScript 提案的 API 进行模拟,
proposals: true
来启用 polyfill 提案。
# 总结
@babel/preset-env
可以完成语法的转译和 polyfill 的加载。@babel/polyfill
包含core-js
和regenerator-runtime
两个模块,可以完整的模拟 ES2015+ 的环境(不包含第4阶段前的提议)。Babel v7.4.0 版本开始弃用,推荐直接使用core-js/stable
和regenerator-runtime/runtime
。@babel/plugin-transform-runtime
是一个可以重复使用 Babel 注入的帮助程序,以节省代码大小的插件。 通常仅在开发时使用,和@babel/runtime
配合使用,@babel/runtime
需要作为生产依赖。@babel/runtime-corejs2
增加了core-js@2
和regenerator-runtime
的依赖,可以引入 polyfill。
# 参考
- @babel/polyfill (opens new window)
- Babel7 转码(二) - @babel/preset-env + @babel/polyfill (opens new window)
- Babel7 转码(五)- corejs3 的更新 (opens new window)
- @babel/polyfill 还是 @babel/plugin-transform-runtime (opens new window)
- @babel/preset-env 与@babel/plugin-transform-runtime 使用及场景区别 (opens new window)
- 了解 Babel 6 & 7 生态 (opens new window)