1. 在开始本章节前先学习一下必备前置知识
- babel-loader:每一个浏览器对js语法兼容性不同,为了使浏览器对js的解析尽量保持一致,所以就出现了Babel。Babel把
ECMAScript 2015+
代码进行降级,用级别低兼容性好的语法重新实现一遍高级语法。
- @babel/polyfill:Babel默认只转换新的Javascript语法,而不转换新的API,它是通过向全局对象和内置对象的
prototype
上添加方法来实现的。比如运行环境中不支持Array.prototype.find
方法,引入polyfill
, 我们就可以使用ES6
方法来编写了。注:Babel 7.4之后不再推荐使用@babel/polyfill(全局污染问题)
- @babel/preset-env: 默认只支持语法转化,需要开启
useBuiltIns
配置才能转化API和实例方法
- babel-runtime: Babel为了解决全局空间污染的问题,提供了单独的包
babel-runtime
用以提供编译模块的工具函数。简单说 babel-runtime
更像是一种按需加载的实现。比如你哪里需要使用 Promise
,只要在这个文件头部import Promise from 'babel-runtime/core-js/promise'
就行了
- babel-plugin-transform-runtime:为了解决
- 多个文件重复引用 相同helpers(帮助函数)=>提取运行时
- 新API方法全局污染 -> 局部引入
2. 安装依赖
pnpm add @babel/polyfill @babel/preset-env babel-loader core-js@2 core-js@3 babel-runtime @babel/plugin-transform-runtime @babel/runtime-corejs3 -D
3. webpack中使用@babel/polyfill
- useBuiltIns: false
- 表示不对
polyfills
处理,此时不对 polyfill 做操作。如果引入 @babel/polyfill,则无视配置的浏览器兼容,引入所有的 polyfill
{
test: /\.js?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
targets: {
"browsers": ["ie >= 8", "chrome >= 62"],
},
presets: [["@babel/preset-env", { useBuiltIns: false }]]
}
}
}
import '@babel/polyfill';
let sum = (a, b) => a + b;
let promise = Promise.resolve();
console.log([1, 2, 3].find(item => item === 2));
- useBuiltIns: entry
- 根据配置的浏览器兼容,引入浏览器需要兼容处理的 polyfill,不能实现按需加载。
corejs
默认是2,如果配置 corejs: 3
, 则import '@babel/polyfill'
需要改成 import 'core-js/stable';import 'regenerator-runtime/runtime';
{
test: /\.js?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [["@babel/preset-env", { useBuiltIns: 'entry', corejs: { version: 3 } }]]
}
}
}
import '@babel/polyfill';
let sum = (a, b) => a + b;
let promise = Promise.resolve();
console.log([1, 2, 3].find(item => item === 2));
import 'core-js/stable';
import 'regenerator-runtime/runtime';
let sum = (a, b) => a + b;
let promise = Promise.resolve();
console.log([1, 2, 3].find(item => item === 2));
- useBuiltIns: usage
- 会根据配置的浏览器兼容,以及你代码中用到的 API 来进行 polyfill,实现了按需添加
{
test: /\.js?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [["@babel/preset-env", { useBuiltIns: 'usage', corejs: { version: 3 } }]]
}
}
}
4. webpack中使用babel-plugin-transform-runtime
- 启用插件
babel-plugin-transform-runtime
后,Babel就会使用babel-runtime
下的工具函数
babel-plugin-transform-runtime
插件能够将这些工具函数的代码转换成require
语句,指向为对babel-runtime
的引用
babel-plugin-transform-runtime
就是可以在我们使用新 API 时自动 import babel-runtime
里面的polyfill
- 当我们使用
async/await
时,自动引入 babel-runtime/regenerator
- 当我们使用 ES6 的静态事件或内置对象时,自动引入
babel-runtime/core-js
- 移除内联
babel helpers
并替换使用babel-runtime/helpers
来替换
{
test: /\.js?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
sourceType: "unambiguous",
presets: [["@babel/preset-env", { useBuiltIns: 'usage', corejs: { version: 3 } }]],
plugins: [
[
"@babel/plugin-transform-runtime",
{
corejs: 3,
helpers: true,
regenerator: true
}
],
]
}
}
}
const p = new Promise(() => { });
function* gen() {}
5.最佳实践
- 项目开发
plugin-transform-runtime
只使用其移除内联复用的辅助函数的特性,减小打包体积
{
test: /\.js?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [["@babel/preset-env", { useBuiltIns: 'usage', corejs: { version: 3 } }]]
plugins: [["@babel/plugin-transform-runtime", { "corejs": false }]]
}
}
}
- 类库开发
- 类库开发尽量不使用污染全局环境的
polyfill
,因此@babel/preset-env
只发挥语法转换的功能
- polyfill由
@babel/plugin-transform-runtime
来处理,推荐使用core-js@3
{
presets: [["@babel/preset-env"]],
plugins: [["@babel/plugin-transform-runtime", corejs: { version: 3 } }]]
}