很多浏览器的内核比较老,一些es6以上的语法无法在他们上面运行,所以需要babel进行降级,转译成es5。
@babel/core
,他就是整个babel的老大,相当于一个人,指挥各个组件怎么转化@babel/preset-env
, 这是一个预设插件的集合,相当于一个指导书,core通过它来看怎么要怎么解析转换babel-loader
,loader是为了让webpack读懂babel的行为安装babel核心库,预设,loader。
npm i @babel/core @babel/preset-env babel-loader -D
-D 为--save dev简称
根目录下创建.babelrc文件:
module.exports = {
presets: ["@babel/preset-env"], // 这个预设其实就是一个plugins的集合
plugins: []
};
然后在webpack中设置module:
module.exports = {
module: {
rules: [
{test: /.js$/, use: 'babel-loader'}
]
}
}
初学webpack可能会容易把babel归于webpack,实际上这是两个东西:
但单单这样配置babel是不能转译所有es6语法的,只能转译基本语法。一些高级语法无法转译(例如Promise
,Array.from
)。拿Promise来说,那些捞捞的浏览器上全局里根本没这些语法,如果Promise在代码中使用到了,babel因为没有Promise实现的代码,指导书里没有,相当于babel不认识它,只能原封不动的转译。
这时候想要完整全部转译还需要babel-polyfill的支持,同时它还支持es6以上更高级语法的转译。
原理就是babel-polyfill会用es5去实现Promise这个功能,并且挂到全局上,就打了个补丁。
注意:polyfill是个概念,意思就是上面描述的原理,而babel-polyfill就是polyfill这个概念的实现。
npm i @babel/polyfill -D
如果不是webpack项目,只是babel项目就不需要配置,直接在使用到es6语法的js文件中引入即可:
import "@babel/polyfill" // module规范
// 或者
require("@babel/polyfill") // commonjs规范
// 下面各种js代码...
但如果在webpack项目中的话就还需要配置才行。具体百度吧,这里就不记了。
上面那种import "@babel/polyfill"
全部引入的使用方式,因为JS全都语法都一次性兼容了,就算没用到的语法也都给你兼容引进去,打包后会有无用代码量,所以体积增大较为明显。
如何按需引入,修改一下babel配置:
"presets": [
[
"@babel/preset-env", // 这个预设其实就是一个plugins的集合
{
"useBuiltIns": "usage",
"corejs": 3
}
]
],
然后把在JS文件中import "@babel/polyfill"
去掉即可。编译后可以看到自动生成按需引入的方式。
可以看出直接引用下面要讲的core.js了,那么其实这种按需引入的方式已经用不到babel-polyfill了,其实不需要安装babel-polyfill,直接安装core.js就行了(下面会讲)。
这个可以看作是一个polyfill集合,在babel官方文档讲babel-polyfill那一章里也推荐使用,且babel-polyfill已在babel7.4之后被弃用。
也可以按需加载,用到了哪个高级语法才给你在打包的时候做对应兼容。
npm i core-js -D
module.exports = {
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
option: {
presets: [ // 预设:指示babel怎么做兼容性处理
"@babel/preset-env",
{
useBuiltIns: 'usage', // 开启按需加载
corejs: {
version: 3, // 指定版本
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: '60',
ie: '9' // 等等
}
},
]
}
}
]
}
}
好像框架都没有预装core.js了,都是脚手架自己的babel处理了
解决前面提到的babel-polyfill的缺点问题,不适合开发库。但是如果只是开发业务项目就不需要配置这个!
@babel/plugin-transform-runtime -D
@babel/runtime -S
在babel配置文件中配置:
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": 3,
"helpers": true,
"regenerator": true,
"useESModules": false
}
]
]
这样polyfill覆盖的api就会以其他形式命名例如_Promise
,原来的Promise函数还在。制作的库不会污染原生api。