# Babel 最佳实践

提到前端语法降级与垫片, 不得不做一番最新的 Babel7 实践总结
# 工具链分类
在开发中解决语法兼容问题, 主要需要用到两方面的工具,分别包括:
- 编译时工具
- 运行时基础库
# 编译时工具
Babel 编译时工具的作用是在代码编译阶段进行语法降级及添加 polyfill
代码的引用语句
主要代表工具有@babel/preset-env
和@babel/plugin-transform-runtime
该类工具仅编译阶段使用, 我们只需安装到package.json
中的devDependencies
中
# 运行时基础库
Babel 的运行时基础库,主要包括core-js
和regenerator-runtime
两个基础库
对于该类基础库, Babel 官方做了一些上层封装, 主要包括以下几个库:
- @babel/polyfill
- @babel/runtime(特殊: 不包含
core-js
的 Polyfill) - @babel/runtime-corejs2
- @babel/runtime-corejs3
对于这类库, 其实都是core-js
和regenerator-runtime
不同版本的封装罢了
这类库是项目运行时必须要使用到的,因此一定要安装到package.json
中的dependencies
中
# 目标环境配置
Browserslist 是一个帮助我们设置目标浏览器的工具,不光是 Babel 用到,其他的编译工具如postcss-preset-env
、autoprefix
中都有所应用。
对于 Browserslist 的配置内容,你既可以放到 Babel 这种特定工具当中,也可以在package.json
中通过browserslist
声明
// package.json
{
"browserslist": "ie >= 11"
}
// .browserslistrc
ie >= 11
// 现代浏览器
last 2 versions and since 2018 and > 0.5%
// 兼容低版本 PC 浏览器
IE >= 11, > 0.5%, not dead
// 兼容低版本移动端浏览器
iOS >= 9, Android >= 4.4, last 2 versions, > 0.2%, not dead
// 通用配置
> 1%, last 2 versions, not dead
# Babel 配置
关于 targets 的配置
@babel/preset-env
的targets
设置有以下几种情况:
- 如果未设置
targets
,那么就使用browserslist
的配置 - 如果对
@babel/preset-env
的targets
参数项进行了设置,那么就不再使用browserslist
的配置, 而是使用targets
的配置 - 如果
targets
不配置,browserslist
也没有配置,那么@babel/preset-env
就对所有 ES2015-ES2020 代码转换为 ES5 兼容
正常情况下,我们推荐使用browserslist
的配置而很少单独配置@babel/preset-env
的targets
# 应用级配置
如果使用新特性,往往是通过基础库(如 core-js)往全局环境添加 Polyfill,如果是开发应用没有任何问题,如果是开发第三方工具库,则很可能会对全局空间造成污染
- 安装依赖
pnpm i @babel/runtime-corejs3 -S
pnpm i @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
- 配置 babel.config.js
module.exports = {
presets: [
[
'@babel/preset-env',
{
corejs: 3,
useBuiltIns: 'usage',
modules: false
}
]
],
plugins: [
// 添加 transform-runtime 插件
[
'@babel/plugin-transform-runtime',
{
corejs: false,
regenerator: false
}
]
]
}
# 工具库配置
transform-runtime
一方面能够让我们在代码中使用非全局版本的 Polyfill,这样就避免全局空间的污染,这也得益于 core-js 的 pure 版本产物特性;另一方面对于 asyncToGeneator 这类的工具函数,它也将其转换成了一段引入语句,不再将完整的实现放到文件中,节省了编译后文件的体积
- 安装依赖
pnpm i @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
pnpm i @babel/runtime-corejs3 -S
- 配置 babel.config.js
module.exports = {
plugins: [
// 添加 transform-runtime 插件
['@babel/plugin-transform-runtime', { corejs: 3 }]
],
presets: [
[
'@babel/preset-env',
{
// 关闭 @babel/preset-env 默认的 Polyfill 注入
useBuiltIns: false,
modules: false
}
]
]
}
# 结合构建工具
# Vite 配置
注意
Vite 中不需要单独配置 babel.config.js
- 安装依赖
# 必须安装 Terser,因为 plugin-legacy 使用 Terser 进行缩小。
pnpm i @vitejs/plugin-legacy terser -D
- vite.config.ts 配置
// vite.config.ts
import legacy from '@vitejs/plugin-legacy'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
// 省略其它插件
legacy({
// 设置目标浏览器,browserslist 配置语法, 如果此处缺省则读取.browserslistrc
targets: ['ie >= 11']
})
]
})
# Rollup 配置
注意
Rollup 中需要单独配置 babel.config.js
- 安装依赖
pnpm i rollup-plugin-babel -D
# rollup-plugin-babel插件并不包含babel包,需要安装必要的babel包依赖
pnpm i @babel/runtime-corejs3 -S
pnpm i @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
- rollup.config.js 配置
// rollup.config.js
import babel from 'rollup-plugin-babel'
export default {
/* 省略其他配置... */
plugins: [
babel({
exclude: 'node_modules/**' // 只编译我们的源代码,忽略第三方代码
})
]
}
# Webpack 配置
注意
Webpack 中需要单独配置 babel.config.js
- 安装依赖
pnpm i @babel/runtime-corejs3 -S
pnpm i @babel/core @babel/preset-env @babel/plugin-transform-runtime babel-loader -D
- webpack.config.js 配置
module.exports = {
/* 省略其他配置... */
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader']
}
]
}
}