史上最清晰易懂的babel配置解析
准备工作
- 新建文件夹
webpack-babel
- 初始化
yarn init -y
- 安装
webpack
yarn add webpack webpack-cli -D
- 安装
webpack
插件yarn add -D html-webpack-plugin clean-webpack-plugin
html-webpack-plugin
用于自动生成index.html
clean-webpack-plugin
用于每次打包时对上一次的dist
文件进行清理,这两个插件跟babel
没关系,只是这里用起来方便 - 安装
webpack-dev-server
用于启动一个web
服务yarn add -D webpack-dev-server
- 新建
src
及入口文件index.js
,内容如下let ele = document.createElement("div") ele.innerHTML = "Hello world!" document.body.appendChild(ele)
- 新建
webpack
配置文件,内容如下const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { index: "./src/index.js" }, devServer: { port: 9998 }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: '管理输出' }) ], }
- 在
package.json
中添加脚本"scripts": { "serve": "webpack-dev-server --config webpack.config.js", "build": "webpack" }
- 跑一下试试
yarn serve
- 打个包试试
yarn build
babel 部分
准备工作就绪之后,开始 babel
相关的部分
-
安装相关包
yarn add -D babel-loader @babel/core @babel/preset-env
babel-loader 允许你使用 Babel 和 webpack 转译
JavaScript
文件
@babel/core 用于转换新的语法
@babel/preset-env 用于配置哪些语法或 API 需要转换 -
首先修改
index.js
内容let a = 1; console.log(a); const fn = () => { }; console.log(fn);
这里使用了
ES6
的let
,和箭头函数
-
使用 Can I use 查询语法支持情况,红色是不支持
可以得知,在IE11
上,这两种语法是都不支持的,实际运行的结果也是如此
-
修改
webpack.config.js
module: { rules: [ { test: /\.m?js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: [ [ '@babel/preset-env', { debug: true, targets: { browsers: ["ie >= 11"] } } ] ], } } } ] },
-
再跑一次
yarn serve
这证明语法已经转换成功,我们修改一下
webpack.config.js
的配置,将模式设置为 development
,以便 yarn build
时看到的代码是未经压缩的。此外,关闭 sourcemap
。
mode: "development", // 强制声明为 development 模式
devtool: "none" // 关闭 sourcemap
- 修改完后,打包
yarn build
如果我们把条件换成支持这两种语法的浏览器呢?
- 修改
webpack.config.js
,chrome 60
版本已经支持let
和箭头函数
,打包后代码 不应该 再被转换。browsers: ["chrome >= 60"]
- 再次打包
yarn build
补充一下,如果开启了
debug
,就可以在终端查看相关代码转换信息
-
换回之前的条件,继续调试
browsers: ["ie >= 11"]
-
清空
index.js
,将index.js
的内容改为const fn = async () => { let r = await Promise.resolve(666) console.log(r) } fn()
-
运行
yarn serve
继续在ie11
中查看
-
从报错可以看到,需要引入
regenerator-runtime
。可以通过以下三种方式解决:
方法1:引入@babel/polyfill
,注意是生产依赖yarn add @babel/polyfill
引入
@babel/polyfill
后,可以发现还引入了两个依赖,core-js
和regenerator-runtime
,而后者正是我们需要的
补充一下
@babel/core
,core-js
和regenerator-runtime
的作用
名称 | 作用 |
---|---|
@babel/core | 处理新语法,比如 模板字符串 ,let ,const ,扩展运算符 等 |
core-js | 处理新 API,比如 Promise ,Set ,Map ,Object.assign 等 |
regenerator-runtime | 处理 async ,await ,generator 等 |
以上内容可在开启 debug
后,在终端查看日志
在 index.js
中引入 @babel/polyfill
,注意,是在所有代码最上面引入
import "@babel/polyfill"
运行
yarn serve
打包看一下
yarn build
一万多行。。
这是由于虽然我们只使用了
async
,但是引入的是完整的 @babel/polyfill
,等于把好多不用的 API 都引了进来,查看打包后的文件,可以看到这时我们就可以使用
useBuiltIns
配置项了
presets: [
[
'@babel/preset-env',
{
debug: true,
targets: {
browsers: ["ie >= 11"]
},
useBuiltIns: "usage" // 看这里
}
]
]
再次打包,剩下 2000 多行,只保留了处理 async
的部分
再回头说一下这个 useBuiltIns 配置项,注意,是
@babel/preset-env
的 useBuiltIns
一共有三个值
值 | 作用 | 是否需要在入口文件引入 @babel/polyfill |
---|---|---|
false | 默认值,无脑引入完整的 polyfill
|
是 |
entry | 引入 targets 中指定的浏览器版本所需的全部 polyfill
|
是 |
usage | 引入代码中用到的并且是 targets 中指定的浏览器版本所需的 polyfill
|
否(安装还是需要安的,就是不需要在入口引入了) |
以上可以通过开启 debug 在控制台中查看
方法二:
首先移除 @babel/polyfill
yarn remove @babel/polyfill
安装@babel/plugin-transform-runtime
,@babel/runtime
yarn add -D @babel/plugin-transform-runtime
yarn add @babel/runtime
安装 @babel/runtime
时可以发现只有 regenerator-runtime
,没有 core-js
,这就意味着 Promise,assign
不会被转译
安装完之后,修改一下
webpack.config.js
中 babel-loader
的部分配置
plugins: [
[
"@babel/plugin-transform-runtime"
]
]
运行一下
正如预期,由于缺少了
core-js
导致部 Promise,assign
不能被支持。如果希望被支持,则还需安装 @babel/polyfill
方法三:
先移除 @babel/runtime
再安装 @babel/runtime-corejs2
yarn remove @babel/runtime
yarn add @babel/runtime-corejs2
修改
webpack.config.js
中 babel-loader
配置项
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
debug: true,
targets: {
browsers: ["ie >= 11"]
// browsers: ["chrome >= 60"]
},
useBuiltIns: "usage"
}
]
],
plugins: [
[
"@babel/plugin-transform-runtime",
{
"corejs": 2,
}
]
]
}
}
}
]
}
修改后,再次运行项目,又恢复了正常 Promise,async,Object.assign
均可以跑在 IE11
上了
- 直接引入
@babel/polyfill
的方式和引入@babel/plugin-transform-runtime + @babel/runtime-corejs2
的方式区别在于,前者会污染全局变量。
例如,如果使用@babel/polyfill
的方式,在IE11
控制台输入Promise
会正常打印,而使用后面的方式,在IE11
控制台中输入Promise
则会提示未定义
- 补充一下,比如多个文件都使用了
class
语法,语法转换时,会出现多个转换的帮助函数,使用@babel/plugin-transform-runtime
用于将多个帮助函数合并为一个,此外,生产环境需要@babel/runtime
配合