系列博客链接
代码
本文的代码是在前面笔记基础上修改的,可以下载代码:github参考或是先看前面的笔记。
Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。
Babel总共分为三个阶段:解析(parse),转换(transform),生成(generate)。
Babel本身不具有任何转化功能,它把转化的功能都分解到一个个plugin
里面。因此当我们不配置任何插件时,经过Babel
输出的代码和输入是相同的。
Babel插件的使用
将插件的名字增加到配置文件中:项目根目录下创建
.babelrc
配置文件或是webapck.config.js
中配置,一般都是在.babelrc
中配置。使用 npm install xxx 进行安装
Babel的配置文件是.babelrc
,存放在项目的根目录下。使用Babel的第一步,就是配置这个文件。
该文件用来设置转码规则和插件,基本格式如下。
{
"presets": [],
"plugins": []
}
Babel简单介绍
preset
preset(预设)就是一系列插件的集合@babel/preset-env
包含所有ES6转译为ES5的插件集合
core-js
转换一些内置类(Promise, Symbols等等)和静态方法(Array.from等)。
@babel/core
是作为Babel的核心存在,Babel的核心api都在这个模块里面。
babel-loader
babel-loader
在webpack中使用,是webpack和Babel之间的通讯桥梁
@babel/polyfill介绍
@babel/preset-env
默认只转译js
语法,而不转译新的API
,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise
等全局对象,以及一些定义在全局对象上的方法(比如Object.assign
)都不会转译。这时就必须使用@babel/polyfill
(内部集成了core-js
和regenerator
)。
使用时,在所有代码运行之前增加import "@babel/polyfill"
或者是在webpack.config.js
入口配置
module.exports = {
entry: ["@babel/polyfill", "./app/js"],
}
因此必须把@babel/polyfill
作为dependencies
而不是devDependencies
@babel/polyfill主要有两个缺点:
1.使用@babel/polyfill
需要做些额外配置,实现打包的时候按需引入,否则会把@babel/polyfill
全部注入代码中会导致打出来的包非常大。
2.@babel/polyfill
会污染全局变量。
Babel7
的一个重大变化就是npm package
名称的变化,把所有babel-*
重命名为@babel/*
,例如:
babel-polyfill
重命名为@babel/polyfill
babel-preset-env
重命名为@babel/preset-env
Babel在webpack中的用法
首先实现对ES6语法的转译
安装babel-loader、 @babel/core、@babel/preset-env
npm i babel-loader -D
npm i @babel/core -D
npm i @babel/preset-env -D
babel-loader@8
需要安装@babel/core7.x
版本。
在webpack.config.js配置
module.exports={
module: {
rules:[
{
test: /\.js$/,
exclude: /node_modules/,
use:{
loader: 'babel-loader',
options:{
presets: [
["@babel/preset-env",{
//targets:表示编译出的代码想要支持的浏览器版本
targets: {
chrome: "67"
}
}]
]
}
}
}
]
}
}
执行npm run build
或npx webpack
就可以看到dist目录下的打包文件,但是只是将ES6的语法进行转译,并没有对ES6新API进行转译,所以我们需要配置@babel/polyfill
解决这个问题。
在index.js
中引入@babel/polyfill
index.js
//index.js
import '@babel/polyfill'
let arr=[
new Promise(()=>{}),
new Promise(()=>{}),
2
]
arr.map((item)=>{
console.log(item)
})
引入@babel/polyfill
前,main.js的大小为29.5KB
引入@babel/polyfill
后,main.js的大小为1MB
注意:以上对比都是在没有targets
这个选项的情况下,因为有些浏览器几乎都支持ES6,在这种情况下,@babel/preset-env
将不会对代码进行处理。
这是因为把@babel/polyfill
对所有API的实现都注入到打包文件中,但是里面很多的API我们在代码中并没有用到,所以需要修改配置,按需引入对应的API。
修改webpack.config.js配置
添加"useBuiltIns": "usage"
以后,需要安装core-js@2
,并且添加"corejs": 2
配置项,这时配置选项比较多,需要在项目根目录下新建.babelrc
文件,在这个文件中配置。
.babelrc
配置如下:
"useBuiltIns"
属性值为"usage"
时,会自动引入@babel/polyfill
,必须保证已经安装了@babel/polyfill
"useBuiltIns"
属性值为"usage"
时,需要添加"corejs": 2
配置项,否则报错,需要安装core-js
首先删掉index.js
中的import '@babel/polyfill'
{
"presets": [["@babel/preset-env",{
"useBuiltIns": "usage", //不需要把polly都打包到代码中,根据代码按需转译
// core-js@3和core-js@2二选一
//"corejs": 3, //npm i --save core-js@3
"corejs": 2 //npm i --save core-js@2
}]]
}
修改webpack.config.js
,删除options
对象
module.exports={
module: {
rules:[
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
}
}
执行npm run build
,打包后的文件大小为165KB
但是,在开发类库或是第三方模块时不适合使用@babel/polyfill
,所以接下来使用@babel/plugin-transform-runtime
来解决这个问题。
@babel/plugin-transform-runtime、@babel/runtime和@babel/runtime-corejs2的用法
@babel/runtime-corejs2:是一个包含Babel modular runtime helpers
和regenerator-runtime
以及core-js
的库。
@babel/runtime:是一个包含Babel modular runtime helpers
和regenerator-runtime
的库。
在配置项中corejs
属性值为默认为false
,如果需要将Promise
等API
进行转译,则需要设置属性值为2
时,并且安装@babel/runtime-corejs2
npm i @babel /plugin-transform-runtime -D
npm i --save @babel/runtime
npm i --save @babel/runtime-corejs2
修改.babelrc文件
{
"plugins": [
["@babel/plugin-transform-runtime",{
"helpers": true,
"regenerator": true,
"useESModules": false,
"corejs": 2
}]
]
}
我们把presets
配置项去掉了,然后npm run build
打包,打开打包后的main.js
查看,虽然把转译了Promise
,但是ES6新语法并没被转译,例如:let
没有被转译为var
。
所以还是需要配置presets
,因为"@babel/preset-env"
包含了对所有ES6语法转译为ES5插件。
再次修改.babelrc文件
{
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-transform-runtime",{
"helpers": true,
"regenerator": true,
"useESModules": false,
"corejs": 2
}]
]
}
添加presets
配置项,然后npm run build
打包,打开打包后的main.js
查看,可以看到let
和箭头函数都被转译为ES5语法了。