准备工作
- 新建文件夹
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
![](https://img.haomeiwen.com/i5408683/81e110d1834f29f4.png)
- 打个包试试
yarn build
![](https://img.haomeiwen.com/i5408683/63d3ec11c00dad24.png)
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
![](https://img.haomeiwen.com/i5408683/13eb55214c362cf2.png)
这证明语法已经转换成功,我们修改一下
webpack.config.js
的配置,将模式设置为 development
,以便 yarn build
时看到的代码是未经压缩的。此外,关闭 sourcemap
。
mode: "development", // 强制声明为 development 模式
devtool: "none" // 关闭 sourcemap
- 修改完后,打包
yarn build
![](https://img.haomeiwen.com/i5408683/d005d69de68259ac.png)
如果我们把条件换成支持这两种语法的浏览器呢?
- 修改
webpack.config.js
,chrome 60
版本已经支持let
和箭头函数
,打包后代码 不应该 再被转换。browsers: ["chrome >= 60"]
- 再次打包
yarn build
![](https://img.haomeiwen.com/i5408683/4f36bf5220d96d38.png)
补充一下,如果开启了
debug
,就可以在终端查看相关代码转换信息
![]()
开启 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
后,在终端查看日志
![](https://img.haomeiwen.com/i5408683/8866cd01b6ea3f1a.png)
在 index.js
中引入 @babel/polyfill
,注意,是在所有代码最上面引入
import "@babel/polyfill"
运行
yarn serve
![](https://img.haomeiwen.com/i5408683/21032acba3f4fa06.png)
打包看一下
yarn build
一万多行。。
![](https://img.haomeiwen.com/i5408683/8281e9ea1c01e8f2.png)
这是由于虽然我们只使用了
async
,但是引入的是完整的 @babel/polyfill
,等于把好多不用的 API 都引了进来,查看打包后的文件,可以看到![](https://img.haomeiwen.com/i5408683/2582e64afae61bac.png)
这时我们就可以使用
useBuiltIns
配置项了
presets: [
[
'@babel/preset-env',
{
debug: true,
targets: {
browsers: ["ie >= 11"]
},
useBuiltIns: "usage" // 看这里
}
]
]
再次打包,剩下 2000 多行,只保留了处理 async
的部分
![](https://img.haomeiwen.com/i5408683/edc8b2a21662e27c.png)
再回头说一下这个 useBuiltIns 配置项,注意,是
@babel/preset-env
的 useBuiltIns
![](https://img.haomeiwen.com/i5408683/c6a274ff5fac2167.png)
一共有三个值
值 | 作用 | 是否需要在入口文件引入 @babel/polyfill |
---|---|---|
false | 默认值,无脑引入完整的 polyfill
|
是 |
entry | 引入 targets 中指定的浏览器版本所需的全部 polyfill
|
是 |
usage | 引入代码中用到的并且是 targets 中指定的浏览器版本所需的 polyfill
|
否(安装还是需要安的,就是不需要在入口引入了) |
以上可以通过开启 debug 在控制台中查看
![](https://img.haomeiwen.com/i5408683/592b18c74ae74b07.png)
![](https://img.haomeiwen.com/i5408683/07c8f91b47990fec.png)
方法二:
首先移除 @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
不会被转译
![](https://img.haomeiwen.com/i5408683/299a629307ee0889.png)
安装完之后,修改一下
webpack.config.js
中 babel-loader
的部分配置
plugins: [
[
"@babel/plugin-transform-runtime"
]
]
运行一下
![](https://img.haomeiwen.com/i5408683/ac72d99edfb1fbf6.png)
正如预期,由于缺少了
core-js
导致部 Promise,assign
不能被支持。如果希望被支持,则还需安装 @babel/polyfill
方法三:
先移除 @babel/runtime
再安装 @babel/runtime-corejs2
yarn remove @babel/runtime
yarn add @babel/runtime-corejs2
![](https://img.haomeiwen.com/i5408683/57a33fcac3981c0c.png)
修改
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
上了
![](https://img.haomeiwen.com/i5408683/4d748abfba18920b.png)
- 直接引入
@babel/polyfill
的方式和引入@babel/plugin-transform-runtime + @babel/runtime-corejs2
的方式区别在于,前者会污染全局变量。
例如,如果使用@babel/polyfill
的方式,在IE11
控制台输入Promise
会正常打印,而使用后面的方式,在IE11
控制台中输入Promise
则会提示未定义
![](https://img.haomeiwen.com/i5408683/3036443b21994052.png)
![](https://img.haomeiwen.com/i5408683/ae3dcec333c73981.png)
网友评论