来到第二部分,主要记录一下 babel-preset-* 预设插件。

前情提要

为什么我打这个标题的时候,脑海里回想起一句话:

Previously on the AMC’s Walking Dead…

Emmmm… 《行尸走肉 第八季》还要一段时间才回归呢 T^T

言归正传,现在来回顾下上一节内容:《什么是 Babel 以及其配置文件》。
Babel 其实就是一个 ECMAScript 的转码器,它能够通过安装和引入相关插件和配置来转译新版本的 ECMAScript 代码成当前环境能够执行的代码。
而一开始的准备工作就是要在项目根目录新建一份名为 .babelrc 的配置文件,Babel 会自动查找并读取内容。

推荐可快速启动项目的 .babel-rc 配置文件如下:

1
2
3
4
5
6
7
8
9
{
"presets": [
"env",
"react"
],
"plugins": [
"transform-runtime"
]
}

且在项目根目录安装这些 babel 插件即可:

1
2
3
$ npm i -D bebel-preset-env
$ npm i -D babel-preset-react
$ npm i -D babel-plugin-transform-runtime

整个初始化项目的目录结构如下:

1
2
3
4
5
6
.
├── .babelrc
├── package.json
└── sample.js

0 directories, 3 files

babel-preset-stage-*:

要了解 Stage-X,那就先来了解一下 TC39。

TC39

TC39,即 Technical Committee 39,是一个推动 JavaScript 发展的委员会。它的成员由各个主流浏览器厂商的代表构成。会议的每一项决议必须大部分人赞同,并且没有人强烈反对才可以通过。

TC39 每年会发布一个新版本,其中包含所有已经完成的特性。

Stage

每一项新特性,要最终纳入ECMAScript规范中,TC39拟定了一个处理过程,称为 TC39 Process。其中共包含5个阶段,Stage 0 ~ Stage 4。

Stage 0: strawman
稻草人阶段。
一种推进 ECMAScript 发展的自由形式,任何 TC39 成员,或者注册为 TC39 贡献者的会员,都可以提交。

Stage 1: proposal
提案阶段。
该阶段产生一个正式的提案。
(1)确定一个带头人来负责该提案,带头人或者联合带头人必须是 TC39 的成员。
(2)描述清楚要解决的问题,解决方案中必须包含例子,API 以及关于相关的语义和算法。
(3)潜在问题也应该指出来,例如与其他特性的关系,实现它所面临的挑战。
(4)polyfill 和 demo 也是必要的。

Stage 2: draft
草案阶段。
草案是规范的第一个版本,与最终标准中包含的特性不会有太大差别。草案之后,原则上只接受增量修改。
(1)草案中包含新增特性语法和语义的,尽可能的完善的形式说明,允许包含一些待办事项或者占位符。
(2)必须包含2个实验性的具体实现,其中一个可以是用转译器实现的,例如Babel。

Stage 3: candidate
候选阶段。
此阶段获得具体实现和用户的反馈。此后,只有在实现和使用过程中出现了重大问题才会修改。
(1)规范文档必须是完整的,评审人和 ECMAScript 的编辑要在规范上签字。
(2)至少要有两个符合规范的具体实现。

Stage 4: finished
完成阶段。
已经准备就绪,该特性会出现在年度发布的规范之中。
(1)通过 Test 262 的验收测试。
(2)有 2 个通过测试的实现,以获取使用过程中的重要实践经验。
(3)ECMAScript 的编辑必须规范上的签字。

babel-preset-stage-*

虽然上面有 5 个阶段,但是只有 4 个 babel-preset-stage-*,因为这类语法规则插件是让我们可以提前使用为正式纳入 ECMAScript 中的实验阶段的新特性,因此最后一个阶段是确认被纳入下一个版本的,所以就只有前面 4 个了,这个逻辑应该可以明白。

这组规则就是使用了实验阶段的 presets,其实如果不是为了探究最新的语法规则,建议就不要使用了,因为提案阶段的还是有可能被改动的。
但是如果想尝试所有新提议的语法特性,那么直接用 babel-preset-stage-0,就可以了,它包含其它 3 个的所有内容。

1
2
3
4
5
6
{
"presets": [
"stage-0"
],
"plugins": []
}

babel-preset-es2015/2016/2017

看到标题大家可能有点纳闷,其实我是简写了,区分为如下:

  • babel-preset-es2015
    只会将 ES2016 编译为 ES5
  • babel-preset-es2016
    只编译 ES2016 的内容(到 ES2015)
  • babel-preset-es2017
    只编译 ES2017 的内容(到 ES2016)

其实看到上面,大家就知道了,使用是很有局限性的。不过相信我们在实际使用中,还是有很多不明就里的同学,直接只使用了 babel-preset-es2015,如下:

1
2
3
4
5
6
{
"presets": [
"es2015"
],
"plugins": []
}

其实有些最新的语法或者是 API 都不是包含在 ES6 中的,而是针对 ES7 的一个提案,所以选用这些插件的好处就是,可以尽可能少地安装不必要的插件,编译速度上也可能会相对快些。

babel-preset-latest

官方声明为已弃用
请使用 babel-preset-env 替代 babel-preset-latest

babel-preset-env

babel-preset-env 在没有任何配置选项的情况下,babel-preset-env 与 babel-preset-latest(或者babel-preset-es2015,babel-preset-es2016和babel-preset-es2017一起)的行为完全相同(但不包含 Stage-X 的)。

不对其进行任何额外配置:

1
2
3
4
5
6
{
"presets": [
"env"
],
"plugins": []
}

如果要对其进行配置选项:

1
2
3
4
5
6
7
8
9
10
{
"presets": [
["env", {
"targets": {
"browsers": ["last 2 versions", "safari >= 7"]
}
}]
],
"plugins": []
}

该例子只包含了支持每个浏览器最后两个版本和safari大于等于7版本所需的polyfill和代码转换。

babel-preset-react

该预设插件在我们写 React 应用的时候是用得到的,babel-preset-react@6.24.1 包含了如下 presets 和 plugins:

1
2
3
4
5
6
7
8
9
10
{
"dependencies": {
"babel-preset-flow": "^6.23.0",
"babel-plugin-syntax-jsx": "^6.3.13",
"babel-plugin-transform-react-display-name": "^6.23.0",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-plugin-transform-react-jsx-source": "^6.22.0",
"babel-plugin-transform-react-jsx-self": "^6.22.0"
}
}

安装:

1
$ npm i -D babel-preset-react

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 用该 preset 生成一个 .babelrc 配置文件
$ echo '{ "presets": ["react"] }' > .babelrc
# 运行如下代码生成一个文件
$ echo '<h1>Hello, world!</h1>' > index.js
# 运行
$ babel index.js
# 输出如下
"use strict";

React.createElement(
"h1",
null,
"Hello, world!"
);

总结

一般地,使用默认就够用了;如果想进行进一步配置的话,可以访问 Babel 中文官方文档的相关配置详解:

https://babeljs.cn/docs/plugins/preset-env

今天深圳天气老热了,刚好能彰显一下本宝的男人味。

参考链接

The TC39 process for ECMAScript features:

http://2ality.com/2015/11/tc39-process.html

Github:tc39/proposals:

https://github.com/tc39/proposals

Standard ECMA-262:

http://www.ecma-international.org/publications/standards/Ecma-262.htm



微信公众号