「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。
- babel只进行JS语法的语法转换,对于JS新的API是无法进行转换的,比如Map, Set, Promise等全局对象
- 在全局对象的上方法,比如ES6 新增的 Array.find方法,babel就无法转换
1. targets
- 配置参数targets表示我们要支持那些平台和那些版本
- 也可以配置浏览器的版本号
- 浏览器的版本号越低,引入的polyfill越多
- 版本号越高,引入的越少
{
test: /.js$/,
use: {
loader: "babel-loader",
options: {
targets: {
"browsers": ["last 2 versions"] // ["IE 6", "chrome 90"]
}
}
}
}
2. babel-polyfill
babel-polyfill是通过向全局对象或者内置对象上的prototyoe上添加方法来实现的,缺点是会造成全局空间污染
3. useBuiltIns
@babel/preset-env是转换语法的插件预设,默认是只转换语法,不转换API的,如果要转换API,需要开启useBuiltIns配置才能转换API和实例方法
useBuiltIns有三个选项
- false: 默认是false,表示不对polyfill做处理,全量引入polyfill; 如果引入@bebel/polyfill,则无视配置浏览器的兼容,引入所有的polyfill
- "entry": 入口文件引入@bebel/polyfill
- "useage": 自动判断代码中用到了什么API来按需加载
3.1 useBuiltIns: false
{
test: /.js$/,
use: {
loader: "babel-loader",
options: {
presets: [
["@babel/preset-env", {
useBuiltIns: false
}]
]
}
}
}
3.2 useBuiltIns: "entry"
- 在项目入口文件引入一次(多次会报错)
- 需要在项目入口文件引入 import "@babel/polyfill
- 会根据配置的浏览器的兼容性来引入浏览器不兼容的polyfill
- 需要指定core-js的版本,默认是2,需要在入口文件配置 import "@babel/polyfill
- 如果core-js指定的版本是3,则需要在入口文件把import "@babel/polyfill" 改成 import "core-js/stable"; import "regenerator-runtime/runtime"
- core-js就是polyfill方法的实现
- 缺点是只会根据浏览器的版本来引入,如果代码中没有使用新的API也会引入当前浏览器不兼容的polyfill
npm install --save core-js@2 npm install --save core-js@3
/src/index.js
// core-js: 2
import "@babel/polyfill";
// core-js: 3
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));
{
test: /.js$/,
use: {
loader: "babel-loader",
options: {
presets: [
["@babel/preset-env", {
useBuiltIns: "entry",
corejs: 3 // corejs: { version: 3 }
}]
]
}
}
}
3.3 useBuiltIns: "usage"
- 如果配置成usage之后,usage会根据浏览器兼容的配置和你代码中用到的API来按需加载
- 当设置成usage之后,不需要在引入@babel/polyfill
{
test: /.js$/,
use: {
loader: "babel-loader",
options: {
presets: [
["@babel/preset-env", {
useBuiltIns: "usage",
corejs: 3 // corejs: { version: 3 }
}]
]
}
}
}
4. babel-runtime
- babel-runtime为了解决全局空间污染的问题单独提供的的包,用于解决编译模块的工具函数
- 它更像是一种按需加载,需要用到什么模块就引入什么模块
- 缺点就是用什么都需要手动引入,非常麻烦且繁琐
npm i babel-runtime --save-dev
import Promise from '@babel-runtime/core-js/promise';
let promise = Promise.resolve();
5. babel-plugin-transform-runtime
- 是为了解决多个文件引用了相同的 helper(帮助函数) 提取到运行时
- 新的API全局方法变成局部引用,会生成多个方法的文件导出来使用
npm i @babel/plugin-transform-runtime @babel/runtime-corejs3 --save-dev
{
test: /.js$/,
use: {
loader: "babel-loader",
options: {
presets: [
["@babel/preset-env", {
useBuiltIns: "usage",
corejs: 3 // corejs: { version: 3 }
}]
]
},
plugins: [
["@babel/plugin-transform-runtime", {
corejs: 3,
helpers: true
}]
]
}
}
5.1 corejs: 3
- 当我们使用ES6的静态事件 或者 内置对象的方法时,会自动引用babel-runtime/core-js
5.2 helpers: true
- 移除内联的babel helpers并替换使用babel-runtime/helpers
- 避免内联的helper在多个文件中重复出现
6. 总结
平时项目开发
- 对于平时项目开发的时候,采用@babel/preset-env来处理兼容问题,缺点是污染全局变量
- useBuiltIns: "usage",来判断浏览器的版本和自动按需引入
- 通过配置@babel-plugin-transform-runtime的helpers: true来减少公共文件的重复生成,提取成公共文件
对于包和库开发的时候
- 尽量减少全局空间的污染
- 可以采用@babel-plugin-transform-runtime的corejs:3 来做polyfill的兼容处理