# Babel 转化
提示
本节内容紧接着上节 Babel。
代码向后兼容其实分为两种兼容,一种是 语法转化、一种是 API 垫片(Shim)。上节内容是简单的对单文件使用了语法转化。本节内容利用 Babel 搭配 Webpack 使用两种兼容方式。
# 语法转化
我们是通过 Webpack 打包整体代码的,在此之前需要用 Babel 对代码进行转化。这样我们就需要 babel-loader (opens new window) 这个 Webpack 转化器,其实就是 Webpack 为了更好的使用 Babel 而包装的转化器。你也可以不安装,自己写一个内部使用 Babel 的 loader。
# 安装
npm install babel-loader --save-dev
2
修改 build.js
打包配置,将 babel-loader
添加至 module.rules
。配置将继续采用传入的方式,你也可以创建配置文件。
// build.js
// build.js
var path = require("path");
var webpack = require("webpack");
webpack(
{
// 需要设置 production,自动开启代码优化功能
// 或设置以下 optimization 手动开启代码优化功能
mode: "none", // 方便查看产物的代码,可以临时设置 none
// 入口
entry: "./src/index.js",
// 输出
output: {
filename: "library.js",
path: path.resolve(__dirname, "dist"),
library: {
name: "library",
type: "umd",
},
},
target: ["web", "es5"],
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
// 传入配置方式 或者 创建配置文件
options: {
presets: ["@babel/preset-env"],
},
},
},
],
},
// optimization: {
// usedExports: true,
// minimize: true,
// concatenateModules: true,
// },
},
(err, stats) => {
if (err || stats.hasErrors()) {
// 这里处理错误
console.log(err, stats);
}
// 处理完成
}
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
运行 node build.js
,重新查看产物,可以发现字符串模板、箭头函数、await
、async
、const
均做了转化。String.prototype.includes
和 Promise
均为未转化。下面 API 转化 将会解决该问题,本小节不做处理。
重新在浏览器运行,发现连 Chrome 都无法运行了。并且抛出 regeneratorRuntime is not defined
错误。这是由于我们使用了 ES8 的 await
、async
的语法糖,其本质就是 Generator
函数。Babel 是通过引入一个辅助函数来实现转化的,Babel 默认我们已经引入了,但我们是没有引入的,才导致该错误。
根据 Babel-简单的使用 小节的提示,我们知道有两种方式。当前我们先使用第一种:在打包的入口文件引入 regenerator-runtime/runtime
。第二种将在 Babel 优化-避免全局污染和重复辅助函数 小节介绍。
// src/index.js
import "regenerator-runtime/runtime";
import { browser } from "./browser";
import { getRandomInt } from "./util";
import { createBackgroudImg, createRandomTextElement } from "./element";
export { browser, getRandomInt, createBackgroudImg, createRandomTextElement };
2
3
4
5
6
7
重新运行 node build.js
,发现在 Chrome 已经可以运行,而 IE 控制台抛出 对象不支持“includes”属性或方法
的异常。这个将在下方 API 转化 小节解决。
# API 转化
默认情况下 @babel/preset-env
是不会转化 API 的,例如新的内置函数 Promise
、WeakMap
,静态方法 Array.from
、Object.assgin
、实例方法 Array.prototype.includes
、Generator
函数等的。官网提供了 @babel/polyfill
(其实就是 core-js
和 regenerator-runtime/runtime
) 来解决改该问题,为你的代码中提供垫片。
注意
从 Babel 7.4.0 起,@babel/polyfill
将替换成 core-js
和 regenerator-runtime/runtime
。官方提示 (opens new window)
我们将安装 core-js@3
,core-js@2
从 2018 年开始就功能冻结,所有新功能只添加到 core-js@3
中。详见 (opens new window)
# 安装 core-js@3,采用
npm install core-js@3 --save
# 安装 core-js@2,不建议
npm install core-js@2 --save
2
3
4
在打包的入口文件引入 core-js/stable
。
提示
这里使用的是 stable
标准已稳定的垫片,如果有需要请使用 core-js
下的具体路径垫片。
// src/index.js
import "core-js/stable";
import "regenerator-runtime/runtime";
import { browser } from "./browser";
import { getRandomInt } from "./util";
import { createBackgroudImg, createRandomTextElement } from "./element";
export { browser, getRandomInt, createBackgroudImg, createRandomTextElement };
2
3
4
5
6
7
8
运行 node build.js
,打开 index.html
。Chrome 和 IE 均运行正常,说明 Babel 的垫片起效果了。