sundway / blog

oh~~
110 stars 6 forks source link

了解 Babel #13

Open sundway opened 7 years ago

sundway commented 7 years ago

最近看了一些 babel 以及 JS 编译器相关的东西,后面分系列对每部分做深入了解。作为第一篇文章,这篇文章总结一些我对 Babel 的整体了解。

一个简单的 JS 编译器

首先可以先看一下一个最简单的 JS 编译器:the-super-tiny-compiler。它分为一下几个步骤:

以上是这个超级简单的编译器编译的几个主要步骤,但是仔细看,其中还有几个关键的概念:

// 你也可以先创建一个访问者对象,并在稍后给它添加方法。 let visitor = {}; visitor.MemberExpression = function() {}; visitor.FunctionDeclaration = function() {}

以上就是一个访问者,当进入到 identifier(关于 identifier 可以看看 [babylon 语法规范](https://github.com/babel/babylon/blob/master/ast/spec.md)) 节点时,就会自动调用 Identifier() 方法,这里每次进入以及出节点和退出节点都会调用一次方法。

## Babel 的编译过程
babel 的编译过程主要是通过 babel-core 来实现的,所以只需要看看 babel-core 是如何做上面的编译过程。
![](https://img.alicdn.com/tfs/TB1jcCGg3MPMeJjy1XcXXXpppXa-832-672.png)

以上是 babel-core 中的依赖,重点几个东西:
* [babylon](https://github.com/babel/babylon) 是比较核心的一部分,主要就是相当于上面的**解析**操作,它严重依赖 acorn 和 acorn-jsx 这两个库。
* [babel-traverse](https://github.com/babel/babel/tree/master/packages/babel-traverse) 是最为复杂的一部分,主要进行了上面的**转化**操作,对 AST 节点进行增加、删除、替换操作。
* [babel-generator](https://github.com/babel/babel/tree/master/packages/babel-generator) 是较为简单的一部分,主要进行了上面的**代码生成**操作,将 AST 转换成代码。

其他的一些库则是一些辅助库,涉及到对节点进行复杂的操作时,可以方便的通过它们简化我们的操作。如:当我们写 babel 插件时,我们可以方便的利用 babel-types 中提供的方法进行操作,当然 babel-types 以及 node 节点都会作为入参传入到我们的 babel 插件的上下文中。

## 编写第一个 babel 插件
![](https://img.alicdn.com/tfs/TB1bdXQhjihSKJjy0FiXXcuiFXa-2878-1596.png)

上图是在 astexplorer 的一个插件 demo。

export default function ({Plugin, types: t}) { return new Plugin('ast-transform', { visitor: { Identifier(node) { return t.identifier(node.name.split('').reverse().join('')); } } }); }


Identifier 方法中定义的一些操作就会在进入以及出 Identifier 节点时执行, 借助 babel-types 帮助函数返回一个新的 Identifier 节点。

以上是对 babel 整个工作流程的的了解,后面会对每一个部分做更进一步的了解。