babel分析

Posted yayaxuping

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了babel分析相关的知识,希望对你有一定的参考价值。

现在都用 ES6 新语法以及 ES7 新特性来写应用了,但是浏览器和相关的环境还不能友好的支持,需要用到 Babel 转码器来转换成 ES5 的代码

相信大家都看到过如下的名词:

  • babel-preset-*
  • babel-plugin-*
  • babel-cli
  • babel-node
  • babel-core
  • babel-runtime
  • babel-plugin-transform-runtime
  • babel-polyfill

一、什么是Bable

例如:

// 转码前
input.map(item => item + 1);
 
// 转码后
input.map(function (item) {
return item + 1;
});
二、Babel 配置文件

使用 Babel 第一步就是在项目根目录创建其配置文件 .babelrc,Babel 会自动查找并读取内容。
该文件是用来设置 Babel 转码器的转码规则和可调用插件,基本格式如下:

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


注意:以下所有 Babel 工具和模块的使用,都必须先写好 .babelrc

presets 字段


官方提供的功用转码规则有:

  • env
  • es2015
  • es2016
  • es2017
  • latest (不推荐, 请使用 env)
  • react
  • flow

# 根据环境自动决定合适插件的规则,
# 转译最新的基础语法
$ npm i --save-dev babel-preset-env
 
# 最新转码规则
# 官方不推荐使用
$ npm i --save-dev babel-preset-latest
 
# 也相当于最新转码规则
$ npm i --save-dev babel-preset-es2015
$ npm i --save-dev babel-preset-es2016
$ npm i --save-dev babel-preset-es2017
 
# 针对不同阶段语法的转码规则(共有4个阶段,选装一个)
$ npm i --save-dev babel-preset-stage-0
$ npm i --save-dev babel-preset-stage-1
$ npm i --save-dev babel-preset-stage-2
$ npm i --save-dev babel-preset-stage-3
# 转译最新的 api 等,为低版本环境提供垫片,其会自动按需引入
$ npm i -D babel-plugin-transform-runtime
{
"presets": [
"env",
"react"
],
"plugins": ["transform-runtime"]
}

babel-preset-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-es2015/2016/2017

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

babel-preset-env

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

babel-plugin-* 插件及与 babel-preset-* 预设插件的关系

preset的预设插件的功能会包含plugin的一些功能,但是同时plugin的有些功能preset不支持,例如:使用 babel-plugin-transform-remove-console。使用这个插件,编译后的代码都会移除 console.*,妈妈再也不用担心线上代码有多余的 console.log 了。

presets / plugins 排序

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

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

babel-core 与 babel-register 的关系

这个就更简单了。

还是 babel-core 包下 register.js 文件的内容:

1
2
3
/* eslint max-len: 0 */
// TODO: eventually deprecate this console.trace("use the `babel-register` package instead of `babel-core/register`");
module.exports = require("babel-register");


就这么短短几行,表明了 babel-core 依赖于 babel-register 来实现一些核心的 API 函数。

所以这么使用场景就很清楚了,需要实时转译 ES6 文件,就用 babel-register,简单单一。

需要使用更高级的功能,也就是需要在实时转译时对转译过程和结果要来把控的话,就用 babel-core,利用其 API 来实现。

最后别忘了,使用这两个 npm 包的时候,不能忘了安装和引入我们前几节所说的 babel-preset-* 和 babel-plugin-* 插件呀!还有 .babelrc 配置文件是一切转译工作进行的前提呀!

以上是关于babel分析的主要内容,如果未能解决你的问题,请参考以下文章

关于babel,你应该知道的一些事

[转] 梦里Babel知多少

Babel插件开发&测试与简易源码分析

Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )(代码片段

babel-plugin-import 实现按需引入

从babel编译结果分析class的实现原理