一、babel的介绍
babel的出现,就是用于解决这样的问题,它是一个编译器,可以把不同标准书写的语言,编译为统一的、能被各种浏览器识别的语言。
由于语言的转换工作灵活多样,babel的做法和postcss、webpack差不多,它本身仅提供一些分析功能,真正的转换需要依托于插件完成。
二、babel的安装
babel可以和构建工具联合使用,也可以独立使用
如果要独立的使用babel,需要安装下面两个库:
@babel/core
:babel核心库,提供了编译所需的所有api@babel/cli
:提供一个命令行工具,调用核心库的api完成编译
npm i -D babel-loader @babel/core @babel/cli
三、babel的配置
配置babel-loader
module: {
rules: [{
test: /\.js$/, // 处理后缀名为js的文件
use: 'babel-loader', // 使用babel-loader进行处理
exclude: /(node_modules)/ //排除node_modules下的文件
}]
}
babel本身没有做任何事情,真正的编译要依托于babel插件和babel预设来完成
babel 预设和 postcss 预设含义一样,是多个插件的集合体,用于解决一系列常见的兼容问题
如何告诉babel要使用哪些插件或预设呢?需要通过一个配置文件.babelrc
// .babelrc 文件配置
{
"presets": [],
"plugins": []
}
四、babel预设
babel有多种预设,最常见的预设是@babel/preset-env
;
@babel/preset-env
安装:
npm i -D @babel/preset-env
.babelrc文件配置
// .babelrc 文件配置
{
"presets": [
"@babel/preset-env"
]
}
兼容的浏览器
@babel/preset-env
需要根据兼容的浏览器范围来确定如何编译,和postcss
一样,可以使用文件.browserslistrc
来描述浏览器的兼容范围
// .browserslistrc 文件配置
last 3 version
> 1%
not ie <= 8
自身的配置
和postcss-preset-env
一样,@babel/preset-env
自身也有一些配置
具体的配置见:https://www.babeljs.cn/docs/babel-preset-env#options
配置方式是:
// .babelrc 文件配置
{
"presets": [
["@babel/preset-env", {
"配置项1": "配置值",
"配置项2": "配置值",
"配置项3": "配置值"
}]
]
}
其中一个比较常见的配置项是usebuiltins
,该配置的默认值是false
由于该预设仅转换新的语法,并不对新的API进行任何处理
例如:
new Promise(resolve => {
resolve()
})
如果遇到没有Promise构造函数的旧版本浏览器,该代码就会报错
core-js
而配置usebuiltins
可以在编译结果中注入这些新的API,它的值默认为false
,表示不注入任何新的API,可以将其设置为usage
,表示根据API的使用情况,按需导入API,使用的是core-js
这个第三方库,该库里边包含了新的API的具体实现
npm i core-js
// .babelrc 文件配置
{
"presets": [
["@babel/preset-env", {
// false: 不用任何的polyfill相关的代码
// usage: 代码中需要哪些polyfill, 就引用相关的api
// entry: 手动在入口文件中导入 core-js/regenerator-runtime, 根据目标浏览器引入所有对应的polyfill
"useBuiltIns": "usage",
// 指定core-js版本,默认使用的是2
"corejs": 3
}]
]
}
regenerator-runtime
这里有时还会有一些特殊的语法 例如 async await
等,这样的语法就不好转换,因此还需要一个新的
库来处理,就需要 regenerator-runtime
来进行处理转换。
安装:
npm i regenerator-runtime
五、完整配置
安装依赖
npm i babel-loader @babel/preset-env @babel/core core-js regenerator-runtime -D
webpack.config.js
// 用来拼接绝对路径的方法
const {resolve} = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// webpack 配置
// 入口起点
entry : './src/index.js',
// 输出
output : {
// 输出文件名
filename : 'js/built.js',
// 输出路径
path : resolve(__dirname, 'dist')
},
// loader 配置
module : {
rules : [
/*
js 兼容性处理:babel-loader @babel/core @babel/preset-env
1. 基本js兼容性处理 --> @babel/preset-env
问题:只能转换基本语法,如Promise不能转换
2. 全部js兼容性处理 --> @babel/polyfill 使用时直接在js文件里面引入:import '@babel/polyfill'
问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了
3. 需要做兼容性处理的就做:按需加载 --> core-js
*/
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 预设:指示babel做怎样的兼容性处理
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定 core-js版本
corejs: {
version: 3
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
]
}
}
]
},
// plugins 的配置
plugins : [
// 详细 plugins 的配置
...
],
//模式
mode : 'development', // 生产模式
// mode : 'production' // 开发模式
}
.browserslistrc
>0.01%
last 2 version
not dead
.babelrc
{
"presets": [
["@babel/preset-env", {
// false: 不用任何的polyfill相关的代码
// usage: 代码中需要哪些polyfill, 就引用相关的api
// entry: 手动在入口文件中导入 core-js/regenerator-runtime, 根据目标浏览器引入所有对应的polyfill
"useBuiltIns": "usage",
// 指定core-js版本,默认使用的是2
"corejs": 3
}]
]
}