Babel是一个编译器,可以将ES6+版本新增加的语法和API转化成ES5代码,让前端开发者可以提前使用ES6+的新特性而不用考虑兼容性问题。
在 Babel7 中,如果使用 .babelrc 配置Babel,默认排除 node_modules
可以使用 babel.config.json 代替 .babelrc,来拒绝这个问题。
在Babel 7 中,配置文件分为 应用级别的配置文件和文件级别的配置文件,.babelrc 默认是文件级别的配置,babel.config.json 默认是应用级别的配置。
Babel本身没有任何编译功能,而是通过选项:环境预设和插件,对代码进行编译的。
Babel转换分为两部分:
通过选项——presets对Babel进行环境预设,实现对一组新语法特性的支持。可以根据项目实际情况设置多个预设。
如果设置了多个预设,预设的执行顺序的从后向前的。
例如:
在Babel7之前的版本中,对于未发布的特性也可以设置预设,但是,Babel7中已经不在支持。
@babel/preset-env
@babel/preset-flow
@babel/preset-react
@babel/preset-typescript
一个普通的vue工程,Babel官方的preset只需要配一个"@babel/preset-env"就可以了。
通过选项——plugins对Babel进行插件配置,转换新API。插件如果配置了多个,他的执行顺序是从前往后的。
支持ES新API:
1、使用@babel/preset-env,配置 useBuiltIns 参数的方式
@babel/preset-env的配置参数:
1.1、 targets:
支持的浏览器
1.2、useBuiltIns:
useBuiltIns项取值可以是"usage" 、 “entry” 或 false(默认)。和polyfill的行为有关系。
1) false:
默认值,不处理api。
2)entry:
全部引入polyfill,需要在入口文件引入 polyfill。如何引用由 corejs 版本决定,详情查看 3. corejs 参数介绍。
3)usage:
按需引入polyfill,不用引入@babel/polyfill。
Babel 编译通常会排除 node_modules,所以 “useBuiltIns”: “usage” 存在风险,可能无法为依赖包添加必要的 polyfill。
{
"presets": [
[
"@babel/preset-env",
{
"modules": false,
"useBuiltIns": "usage",
"corejs": "3",
"targets": ">0.2%, not dead, Firefox >= 52, IE >= 8"
}
]
],
}
1.3、 corejs:
取值为2(默认)和3,只在useBuiltIns: "entry | usage"时有效。
需要注意的是:
1) corejs取值为2
如果安装了 @babel/polyfill 不用在额外安装 core-js@2,因为 @babel/polyfill 模块包含 core-js 和一个自定义的 regenerator runtime 。
// babel 配置
{
"presets": [
[
"@babel/preset-env",
{
"modules": false,
"useBuiltIns": "entry",
"corejs": 2,
}
]
],
}
// 安装 @babel/polyfill
npm i @babel/polyfill -S
// 入口处引入
import '@babel/polyfill';
2) corejs取值为3
必须安装core-js@3版本才可以,否则Babel会转换失败并提示:
@babel/polyfill
is deprecated. Please, use required parts of core-js
and regenerator-runtime/runtime
separately
// babel 配置
{
"presets": [
[
"@babel/preset-env",
{
"modules": false,
"useBuiltIns": "entry",
"corejs": 3,
}
]
],
}
// 安装 core-js@3
npm i core-js@3 -D
// 入口处引入
import 'core-js/stable'
import 'regenerator-runtime/runtime'
1.4、 modules:
该项用来设置是否把ES6的模块化语法改成其它模块化语法。
取值为:“amd”、“umd” 、 “systemjs” 、 “commonjs” 、“cjs” 、“auto” (默认)、false。
默认代码里import都被转码成require。
如果我们将参数项改成false,那么就不会对ES6模块化进行更改,还是使用import引入模块。
使用ES6模块化语法有什么好处呢?
在使用Webpack一类的打包工具,可以进行静态分析,从而可以做tree shaking等优化措施。
上面配置方式的问题有哪些?
1)全局污染问题
babel 的 polyfill 机制是,对于例如 Array.from 等静态方法,直接在 global.Array 上添加;对于例如 includes 等实例方法,直接在 global.Array.prototype 上添加。这样直接修改了全局变量的原型,有可能会带来意想不到的问题。
2)代码重复
代码在编译的过程中会使用一些 helper (辅助函数),会直接写在文件中,如果多个文件都是用了相同的语法,那个两个文件中都会有这个语法对应的 helper 。这种代码重复会造成文件尺寸增大。
那么如何来解决上面的两个问题呢?答案就是使用插件
删除内联 helper,运行时从 @babel/runtime-corejs3/helpers 模块中引入 helper,避免全局污染同时减少文件尺寸。
2、使用@babel/plugin-transform-runtime和@babel/runtime-corejs3
@babel/runtime-corejs3
@babel/runtime-corejs3/helpers 模块下的保存着 Babel 编译所需要的各种 helper,不再将 helper 内联到各个文件中去,直接从 @babel/runtime-corejs3/helpers 模块中入即可。
@babel/plugin-transform-runtime
删除内联 helper,从 @babel/runtime-corejs3/helpers 模块中引入 helper。
用法:
{
"presets": [
[
"@babel/preset-env",
{
"modules": false,
"targets": ">0.2%, not dead, Firefox >= 52, IE >= 8"
}
]
],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": "3",
"helpers": true,
"regenerator": true
}
]
]
}
2.1、@babel/plugin-transform-runtime 配置参数说明
1)corejs
2 | 3 | false(默认)。
指向选项的值为数字,即选择哪个版本的@babel-runtime-corejs:
2)helpers
true(默认) | false
从 @babel/runtime-corejs/helpers 模块中引入 helper。代替内联 helper。
3)regenerator
true(默认) | false
切换是否将generator函数转换为使用不污染全局作用的regenerator运行时。
参考文献:
https://juejin.cn/post/7033383643976630302
babel 在转译的过程中,对 syntax 的处理可能会使用到 helper 函数,对 api 的处理会引入 polyfill。
默认情况下,会有以下两个问题:
@babel/plugin-transform-runtime 的作用是将 helper 和 polyfill 都改为从一个统一的地方引入,并且引入的对象和全局变量是完全隔离的,这样解决了上面的两个问题。