剖析Babel-Babel总览

关注“重度前端”

助力前端深度学习

━━━━━

前言

详细介绍下babel的内容,处理代码的过程以及内部机制,对我们以后的工程化使用很有帮助。本文内容过多,算是抛砖引玉,让我们可以有个整体的了解,具体的知识点可以细细的研究。

Babel的解析引擎

Babel使用的引擎是babylon,babylon并非由babel团队自己开发的,而是fork的acorn项目,acorn的项目本人在很早之前在兴趣部落1.0在构建中使用,为了是做一些代码的转换,是很不错的一款引擎,不过acorn引擎只提供基本的解析ast的能力,遍历还需要配套的acorn-travesal, 替换节点需要使用acorn-,而这些开发,在Babel的插件体系开发下,变得一体化了

Babel的工作过程

Babel会将源码转换AST之后,通过便利AST树,对树做一些修改,然后再将AST转成code,即成源码。

640?wx_fmt=png

Babel的前序工作——Babylon、babel-types:code转换为AST

Babel转AST树的过程涉及到语法的问题,转AST树一定有对就的语法,如果在解析过程中,出现了不符合Babel语法的代码,就会报错,Babel转AST的解析过程在Babylon中完成

解析成AST树使用babylon.parse方法

640?wx_fmt=png

结果如下

640?wx_fmt=png

AST如下

640?wx_fmt=png

关于AST树的详细定义Babel有文档

https://github.com/babel/babylon/blob/master/ast/spec.md

关于AST树的定义

640?wx_fmt=png

ast中的节点都是继承自Node节点,Node节点有type和loc两个属性,分别代表类型和位置,

其中位置定义如下

640?wx_fmt=png

位置节点又是由source(源码string), 开始位置,结束位置组成,start,end又是Position类型

640?wx_fmt=png

节点又包含行号和列号

再看Program的定义

640?wx_fmt=png

Program是继承自Node节点,类型是Program, sourceType有两种,一种是script,一种是module,程序体是一个声明体Statement或者模块声明体ModuleDeclaration节点数组

Babylon支持的语法

Babel或者说Babylon支持的语法现阶段是不可以第三方扩展的,也就是说我们不可以使用babylon做一些奇奇怪的语法,换句话说

不要希望通过babel的插件体系来转换自己定义的语法规则

那么babylon支持的语法有哪些呢,除了常规的js语法之外,babel暂时只支持如下的语法

Plugins
  • estree

  • jsx

  • flow

  • doExpressions

  • objectRestSpread

  • decorators (Based on an outdated version of the Decorators proposal. Will be removed in a future version of Babylon)

  • classProperties

  • exportExtensions

  • asyncGenerators

  • functionBind

  • functionSent

  • dynamicImport

如果要真要自定义语法,可以在babylon的plugins目录下自定义语法

https://github.com/babel/babylon/tree/master/src/plugins

Babel-types,扩展的AST树

上面提到的babel的AST文档中,并没有提到JSX的语法树,那么JSX的语法树在哪里定义呢,同样jsx的AST树也应该在这个文档中指名,然而babel团队还没精力准备出来

640?wx_fmt=png

实际上,babel-types有扩展AST树,babel-types的definitions就是天然的文档,具体的源码定义在这里

640?wx_fmt=png


Babel的中序工作——Babel-traverse、遍历AST树,插件体系

遍历的方法

Babel负责便利工作的是Babel-traverse包,使用方法

640?wx_fmt=png

遍历结点让我们可以获取到我们想要操作的结点的可能,在遍历一个节点时,存在enter和exit两个时刻,一个是进入结点时,这个时候节点的子节点还没触达,遍历子节点完成的时刻,会离开该节点,所以会有exit方法触发

访问节点,可以使用的参数是path参数,path这个参数并不直接等同于节点,path的属性有几个重要的组成,如下

640?wx_fmt=png

举个栗子,如下的代码会将所有function变成另外的function

640?wx_fmt=png

结果如下

640?wx_fmt=png

注意这里我们使用babel-types来判别node的类型,使用path的replaceWithSourceString方法来替换节点

但这里在babel的文档中也有提示,尽量少用replaceWithSourceString方法,该方法一定会调用babylon.parse解析代码,在遍历中解析代码,不如将解析代码放到遍历外面去做

其实上面的过程只是定义了如何遍历节点的时候转换节点

babel将上面的便利操作对外开放出去了,这就构成了babel的插件体系

babel的插件体系——结点的转换定义

babel的插件就是定义如何转换当前结点,所以从这里可以看出babel的插件能做的事情,只能转换ast树,而不能在作用在前序阶段(语法分析)

这里不得不提下babel的插件体系是怎么样的,babel的插件分为两部分

babel-preset-xxx

babel-plugin-xxx

preset: 预设, preset和plugin其实是一个东西,preset定义了一堆plugin list

这里值得一提的是,preset的顺序是倒着的,plugin的顺序是正的,也就是说

preset: [‘es2015’, ‘react’], 其实是先使用react插件再用es2015

plugin: [‘transform-react’, ‘transfrom-async-function’] 的顺序是正的遍历节点的时候先用transform-react再用transfrom-async-function

babel插件编写 这里就不多说了,有兴趣的可以看下官方文档;

一些AST树的创建方法

在写插件的过程中,经常要创建一些AST树,常用的方法如下

使用babel-types定义的创建方法创建

640?wx_fmt=png

如果使用这样创建一个ast节点,肯定要累死了

  • 使用replaceWithSourceString方法创建替换

  • 使用template方法来创建AST结点

比如上面的var a = 1可以使用

640?wx_fmt=png

当然也可以简单写

640?wx_fmt=png

接下来就可以用path的增、删、改操作进行转换了

Babel的后序工作——Babel-generator、AST树转换成源码

Babel-generator的工作就是将一颗ast树转回来,具体操作如下

640?wx_fmt=png

至此,代码转换就算完成了

结语

最后,就像babylon官网感觉acorn一样,babel为前端界做了一件awesome的工作,有了babel,不仅仅可以让我们的新技术的普及提前几年,我们可以通过写插件做更多的事情,比如做自定义规则的验证,做node的直出node端的适配工作等等。

参考资料

babel官网: https://babeljs.io

babel-github: https://github.com/babel

babylon: https://github.com/babel/babylon

acorn: https://github.com/marijnh/acorn

babel-ast文档: https://github.com/babel/babylon/blob/master/ast/spec.md

babel插件cookbook: https://github.com/thejameskyle/babel-handbook/blob/master/translations/zh-Hans/plugin-handbook.md

关于本文

转载自AlloyTeam:http://www.alloyteam.com/2017/04/analysis-of-babel-babel-overview/

640?wx_fmt=png

 重度前端--助力深度学习

为web前端同行提供有价值、有深度的技术文章

官网:http://bigerfe.com【建设中】

640?wx_fmt=jpeg

长按二维码关注我

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值