相信大家看了第一节《Babel 入门教程(一):什么是 Bable 及其配置文件》后,还是有点疑惑的,到底什么时候要用 presets,什么时候要用 plugins?第二节《Babel 入门教程(二):babel-preset-* 预设插件》已经讲解了相关的 presets,那么 plugins 又是指什么,可以用的 plugins 有哪些,可以在哪里找?plugins 与 presets 的关系有是什么?

不急,本节会讲。

前情提要

Previously on the AMC’s Walking Dead…

(够了!…

言归正传,现在来回顾下上一节内容:《babel-preset-* 预设插件》。
主要介绍了 babel-preset-stage-0/1/2/3、babel-preset-latest、babel-preset-es2015/2016/2017 以及 babel-preset-env,还有 babel-preset-react。这几个是用的比较多的,或者说经常使用的,也可以说涵盖这几个基本上够满足我们的开发需求了。

babel-preset-stage-0/1/2/3、babel-preset-latest、babel-preset-es2015/2016/2017 以及 babel-preset-env,这一组是比较容易混淆使用的,功能相近,且个别有重复,总而言之,babel-preset-latest 已经被官方废弃了,babel-preset-env 不包含 babel-preset-stage-0/1/2/3,但是它可以完全替代 babel-preset-latest 和 babel-preset-es2015/2016/2017,它可以根据我们的环境自动启用相关的转译功能,而且还支持自定义配置。所以,我们如果在开发中针对 ECMAScript 的语法转译一般只需要引入 babel-preset-env 就足够了。

babel-preset-react 不同于前面几个,它是当我们用 React.js 来开发应用的时候需要引入的,具体在这节会讲解。

至于更多可用的 babel-preset-* 在哪里能够找到,那就当然是 npm 官网上来,地址如下:
https://www.npmjs.com/search?q=babel-preset

babel-preset- 与 babel-plugin- 的关系

一开始我也是没有弄明白两者关系,.babelrc 配置文件的配置应该尽可能地简单才是,为什么会出现两个大的配置选项?

其实还得从选项原本含义上去理解,第一节说过,.babelrc 文件一般包含如下两个配置选项:

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

presets 字段指的是预设插件,也就是说,它是一堆 plugins 组成的集合,已经包含默认的设定,安装完就能使用,起到方便快捷的作用,相当于装了一组组工具的工具箱;而 plugins 字段是要填写单独的插件,也就是一份一份的工具(虽然其中免不了有相关的依赖)。

下面举一个很简单直观的例子

babel-plugin-transform-react-jsx

来安装使用一个 babel-plugin-* 类型的插件。该插件能够将 jsx 语法进行转译。

安装相关 npm 包:

1
$ npm i -D babel-plugin-transform-react-jsx

引入到 .babelrc 文件:

1
2
3
4
5
6
{
"presets": [],
"plugins": [
"transform-react-jsx"
]
}

原 ES6 代码:

1
2
3
4
var profile = <div>
<img src="avatar.png" className="profile" />
<h3>{[user.firstName, user.lastName].join(' ')}</h3>
</div>;

转译后代码:

1
2
3
4
var profile = React.createElement("div", null,
React.createElement("img", { src: "avatar.png", className: "profile" }),
React.createElement("h3", null, [user.firstName, user.lastName].join(" "))
);

babel-plugin-transform-react-display-name

来安装使用一个 babel-plugin-* 类型的插件。该插件能够将自动添加 displayNameReact.createClass 的函数调用的实参配置对象中。

安装相关 npm 包:

1
$ npm i -D babel-plugin-transform-react-display-name

引入到 .babelrc 文件:

1
2
3
4
5
6
{
"presets": [],
"plugins": [
"transform-react-display-name"
]
}

原 ES6 代码:

1
2
var foo = React.createClass({}); // React <= 15
var bar = createReactClass({}); // React 16+

转译后代码:

1
2
3
4
5
6
var foo = React.createClass({
displayName: "foo"
}); // React <= 15
var bar = createReactClass({
displayName: "bar"
}); // React 16+

babel-preset-react

来安装使用一个 babel-preset-* 类型的插件。

安装相关 npm 包:

1
$ npm i -D babel-preset-react

引入到 .babelrc 文件:

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

然后先来查看下这个插件包的依赖:

1
$ cat ./node_modules/babel-preset-react/package.json

然后可以注意到其 dependencies 字段:

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"
},
}

是不是很惊讶地看到了我们刚才安装的两个插件:babel-plugin-transform-react-jsxbabel-plugin-transform-react-display-name

也就是说,刚才那两个插件的功能,在这个预设插件 babel-preset-react 都包含了。不信的话,大家可以亲自动手将上面两个例子的 ES6 的代码集中起来,用该预设插件进行转译,是完全能够成功的。

总结关系

所以从上面的例子可以很清楚地知道,presets 预设插件是一堆 plugins 插件的集合;如果我们不采用 presets,那么也完全可以用 plugins 插件,来单独引入某项功能。

再举个更清晰的栗子,比如说我们的代码相较于 ES5 语法,只使用了 ES6 语法中新引入的箭头函数,那么按道理来说,我们只安装引入能够编译箭头函数的 babel 插件就够了,这个插件就是 babel-plugin-transform-es2015-arrow-functions

安装该 npm 包:

1
$ npm i -D babel-plugin-transform-es2015-arrow-functions

引入到配置文件:

1
2
3
4
5
{
"plugins": [
"transform-es2015-arrow-functions"
]
}

另外,还要说明的是,总会有一些方法是 presets 预设插件中不提供的,这时候还就需要单独引入 plugins 插件了。

然后我又来举栗子了,使用 babel-plugin-transform-remove-console。使用这个插件,编译后的代码都会移除 console.*,妈妈再也不用担心线上代码有多余的 console.log 了。当然很多时候,我们如果使用 webpack,会在 webpack 中配置代码压缩以及剔除打印功能。

安装该 npm 包:

1
$ npm i -D babel-plugin-transform-remove-console

引入到配置文件:

1
2
3
4
5
{
"plugins": [
"transform-remove-console"
]
}

自定义预设或插件

Babel 支持我们自定义的预设 (presets) 或插件 (plugins) 。

我们可以编写好 presets 或者 plugins 插件,然后发布到 npm 上,然后同上用 npm install 方式安装到本地项目,再于 .babelrc 配置文件中引入。

如果是名为 “babel-plugin-myPlugin”,那么直接在 .babelrc 中的 plugins 字段中,填写入 myPlugin 即可。
presets 同理。

presets / plugins 排序

plugins 和 presets编译,也许会有相同的功能,或者有联系的功能,按照怎么的顺序进行编译?答案是会按照一定的顺序。

  • 具体而言,plugins 优先于 presets进行编译。
  • plugins 按照数组的 index 增序(从数组第一个到最后一个)进行编译。
  • presets 按照数组的 index 倒序(从数组最后一个到第一个)进行编译。因为作者认为大部分会把 presets 写成 [“es2015”, “stage-0”]。具体细节可以看官方文档。

结语

有没有发现每次新文章的前情提要都会对上一节有更全更细致的补充,这是因为综合了几位在后台问了相关问题的读者的意见,然后进行完善的。把一件复杂的事情阐述清楚并不简单,但是一件很具挑战很具意义的事情。希望我的文章能够理清自己头绪的同时,也能给你们带来清晰的思路。

最近手游《旅行青蛙(中文译名)》很火,我中午试玩了一下,emmmm,看不懂日文,弃坑了。

提示:在应用商店搜的时候不能搜中文译名哦,要搜日文名,百度下就知道了哈~



微信公众号