聊一聊 Babel
# 聊一聊 Babel
原文链接:https://juejin.cn/post/6844903849442934798 (opens new window)
Babel 大概分为三大部分:
解析:将代码(其实就是字符串)转换成 AST(抽象语法树)
转换:访问 AST 的节点进行变换操作生成新的 AST
生成:以新的 AST 为基础生成代码
# 解析
代码解析,也就是我们常说的 Parser,用于将一段代码(文本)解析成一个数据结构。
文本转换成 AST 有两个关键步骤:
词法分析:将代码(字符串)分割为 token 流,即语法单元数组(语法单元包括数字、括号、标识符、运算符、注释等)
语法分析:分析 token 流(上面生成的数组)并生成 AST(语法分析很复杂,因为要分析各种语法的可能性)
在我们 parser 的过程中,应该换一个角度看待代码,我们平时工作用的代码,本质是就是字符串或者一段文本,它没有任何意义,是 JavaScript 引擎赋予了它意义,所以我们在解析过程中代码只是一段字符串。
# 转换
在 Babel 中我们最常使用的就是代码转换,大家常用的 Babel 插件就是定义代码转换规则而生的,而代码解析和生成这一头一尾主要是由 Babel 负责。
比如我们要用 babel 做一个 React 转小程序的转换器,babel 工作流程的粗略情况是这样的:
babel 将 React 代码解析为抽象语法树
开发者利用 babel 插件定义转换规则,根据原本的抽象语法树生成一个符合小程序规则的新抽象语法树
babel 则根据新的抽象语法树生成代码,此时的代码就是符合小程序规则的新代码
例如 Taro 就是用 babel 完成的小程序语法转换,转换代码的关键就是根据当前的抽象语法树,以我们定义的规则生成新的抽象语法树,转换的过程就是生成新抽象语法树的过程。
抽象语法树是一个树状数据结构,我们要生成新语法树,那么一定需要访问 AST 上的节点,因此我们需要一个工具(遍历器 traverser)来遍历抽象语法树的节点。
我们之前的遍历器 traverser 接收两个参数,一个是 ast 节点对象,一个是 visitor,visitor 本质是挂载不同方法的 JavaScript 对象,visitor 也叫做访问者,它会访问 ast 上每个节点,然后根据针对不同节点用相应的方法做出不同的转换。
# 生成
生成代码这一步实际上是根据我们转换后的抽象语法树来生成新的代码,接受一个对象 ast,通过递归生成最终的代码。