介绍
babel
是 Javascript
的编译语法器,确切来说是源码到源码的编译器,通常也叫做“转换编译器(transpiler)。意思是说你为 Babel 提供一些 JavaScript 代码,Babel 更改这些代码,然后返回给你新生成的代码。
抽象语法数(AST)
这个处理过程中的每一步都涉及到创建或是操作抽象语法树,亦称 AST。
1 2 3
| function square(n) { return n * n; }
|
这个程序可以被表示成如下的一棵树:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| - FunctionDeclaration: - id: - Identifier: - name: square - params [1] - Identifier - name: n - body: - BlockStatement - body [1] - ReturnStatement - argument - BinaryExpression - operator: * - left - Identifier - name: n - right - Identifier - name: n
|
或是如下所示的 JavaScript Object(对象):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| { type: "FunctionDeclaration", id: { type: "Identifier", name: "square" }, params: [{ type: "Identifier", name: "n" }], body: { type: "BlockStatement", body: [{ type: "ReturnStatement", argument: { type: "BinaryExpression", operator: "*", left: { type: "Identifier", name: "n" }, right: { type: "Identifier", name: "n" } } }] } }
|
你会留意到 AST 的每一层都拥有相同的结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| { type: "FunctionDeclaration", id: {...}, params: [...], body: {...} }
{ type: "Identifier", name: ... }
{ type: "BinaryExpression", operator: ..., left: {...}, right: {...} }
|
注意:出于简化的目的移除了某些属性
这样的每一层结构也被叫做 节点(Node)。 一个 AST 可以由单一的节点或是成百上千个节点构成。
Babel 的处理步骤
Babel 的三个主要处理步骤分别是: 解析(parse),转换(transform),生成(generate)。
解析
解析步骤接收代码并输出 AST。 这个步骤分为两个阶段:**词法分析(Lexical Analysis) **和 语法分析(Syntactic Analysis)。
词法分析
词法分析阶段把字符串形式的代码转换为 令牌(tokens) 流。
你可以把令牌看作是一个扁平的语法片段数组:
1 2 3 4 5 6
| [ { type: { ... }, value: "n", start: 0, end: 1, loc: { ... } }, { type: { ... }, value: "*", start: 2, end: 3, loc: { ... } }, { type: { ... }, value: "n", start: 4, end: 5, loc: { ... } }, ... ]
|
每一个 type 有一组属性来描述该令牌:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| { type: { label: 'name', keyword: undefined, beforeExpr: false, startsExpr: true, rightAssociative: false, isLoop: false, isAssign: false, prefix: false, postfix: false, binop: null, updateContext: null }, ... }
|
和 AST 节点一样它们也有 start,end,loc 属性。
语法分析
语法分析阶段会把一个令牌流转换成 AST 的形式。 这个阶段会使用令牌中的信息把它们转换成一个 AST 的表述结构,这样更易于后续的操作。
转换
转换步骤接收 AST 并对其遍历,在此过程对节点进行添加、更新、删除等操作。这个是 Babel 编译器 中最复杂的过程,也是插件将来要介入工作的部分。
生成
代码生成步骤把最终(经过一系列转换后)的 AST 转成字符串形式的代码,同时还会创建 源码映射
代码生成其实很简单:深度优先遍历整个 AST,然后构建可以表示转换后代码的字符串。
遍历
想要转换 AST 你需要进行递归的树形遍历。