[2] Babel原理

141 阅读3分钟

一、工作原理 AST

Babel 本质上就是在操作 AST 来完成代码的转译。

1.1 是什么

image.png

// es2015 的 const 和 arrow function
const add = (a, b) => a + b;

// Babel 转译后
var add = function add(a, b) {
  return a + b;
};

Babel 的功能很纯粹。我们传递一段源代码给 Babel,然后它返回一串新的代码给我们。就是这么简单,它不会运行我们的代码,也不会去打包我们的代码。它只是一个编译器。

1.2 Babel解析过程

image.png

  1. Parse(解析) :将源代码转换成AST抽象语法树)。 @babel/parser
  2. Transform(转换) :对于 AST 进行变换一系列的编辑操作。
  • @babel/traverse可以通过「深度优先」的方式遍历AST
  • 对于遍历到的每条路径-@babel/types提供用于修改AST节点的节点类型数据。
  1. Generate(代码生成) :将第二步将转换过的AST输出。@babel/generator

@babel/core 模块则是将三者结合使得对外提供的API做了一个简化。

1.3 整个Babel底层编译能力

babel-core提供了以上提到的三个步骤的能力。

image.png

@babel/core(由 @babel/parser@babel/traverse@babel/types@babel/generator等组成),他们提供了Babel编译JS的能力。

二、AST

babel默认是使用Esprima去解析AST的。
例如: image.png 解析:

一个 AST 的根节点始终都是 Program,上面的例子我们从 declarations 开始往下读:
一个VariableDeclaration(变量声明):声明了一个 name 为 add 的ArrowFunctionExpression(箭头函数):

  • params(函数入参):a 和 b
  • 函数体:函数主体是一个BinaryExpression(二项式),一个标准的二项式分为三部分:
    • left(左边):a
    • operator(运算符):加号 +
    • right(右边):b

三、babel工作过程

3.1 Parse(解析)

Parse 阶段可以细分为两个阶段:词法分析(Lexical Analysis, LA)和语法分析(Syntactic Analysis, SA)。

(1)词法分析:

词法分析阶段可以看成是对代码进行“分词”,它接收一段源代码,然后执行一段 tokenize 函数,把代码分割成被称为Tokens 的东西。会移除空白符、注释等。

Tokens 是一个一纬数组,由一些代码的碎片组成,比如数字、标点符号、运算符号等等等等,

image.png

  • Keyword: 关键字
  • Identifier: 唯一标志, 标记
  • Punctuator: 标点符号
  • Numeric: 数字

(2)语法分析:

词法分析之后,代码就已经变成了一个 Tokens 数组了,现在需要通过语法分析把 Tokens 转化为树形的形式即 AST

同时,验证语法。语法如果有错的话,抛出语法错误。

生成树的时候,解析器会删除一些没必要的标识 tokens(比如:不完整的括号),因此 AST 不是 100% 与源码匹配的。

3.2 Transform(转换)

AST 中有很多相似的元素,它们都有一个 type 属性,这样的元素被称作节点。一个节点通常含有若干属性,可以用于描述 AST 的部分信息。

比如这是一个最常见的 Identifier 节点:

{
    type: 'Identifier',
    name: 'add'
}


表示这是一个标识符。

所以,操作 AST 也就是操作其中的节点,可以增删改这些节点,从而转换成实际需要的 AST

ps: Babel 对于 AST 的遍历是深度优先遍历,对于 AST 上的每一个分支 Babel 都会先向下遍历走到尽头,然后再向上遍历退出刚遍历过的节点,然后寻找下一个分支。

3.3 Generate(代码生成)

经过上面两个阶段,需要转译的代码已经经过转换,生成新的 AST 了,最后一个阶段理所应当就是根据这个 AST 来输出代码

结尾:经过这三个阶段,代码就被 Babel 转译成功了。

四、推荐工具