AST的定义
在计算机科学中,抽象语法树(Abstract Syntax Tree,AST),或简称语法树(Syntax Tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构
怎么生成AST
- 词法分析: 也称之为扫描(scanner),简单来说就是调用 next() 方法,一个一个字母的来读取字符,然后与定义好的 JavaScript 关键字符做比较,生成对应的Token。Token 是一个不可分割的最小单元:例如 var 这三个字符,它只能作为一个整体,语义上不能再被分解,因此它是一个 Token;一个Token令牌被创建,并被发送到
解析器(parser)。其余的字节流也是如此. - 语法分析: 将生成的Token令牌去跟js的关键字作对比,讲词法分析出来的Token 转化成有语法含义的抽象语法树结构。同时,验证语法,语法如果有错的话,抛出语法错误。
- 随着 JavaScript 语言的发展,由一些大佬创建的项目 ESTree 用于更新 AST 规则,目前已成为社区标准。然后社区中一些其它项目比如 ESlint 和 Babel 就会使用 ESTree 或在此基础上做一些修改,然后衍生出自己的一套规则,并制作相应的转换工具,暴露出一些 API 给开发者使用。
AST的直观体验
ast部分节点类型
AST能做什么
语法检查、代码风格检查、格式化代码、语法高亮、错误提示、自动补全、通过ast对源文件增删改;在开源工具中的应用,比如 ESLint、Babel、Vue.js 、Rollup等社区上多项著名项目都依赖其能力
常用JavaScript Parser解析工具有:
- esprima
- acorn 体积小,功能较少
- babel/paser 基于babylon,功能强大,但是比较重
- jscodeshift 功能强大,没有文档,需要看源码。感兴趣可以点击官方的 collection 及 extensions 查看 API
下面我们尝试用jscodeshift这个包做一些基于ast的修改(为什么用这个包而不是acorn,因为这个包提供了一些快捷的方法供我们使用,但是其他的需要我们自己去写增删改查就比较费事)
npm install jscodeshift --save
新建一下文件 edit.js 然后 node edit.js
const jf = require("jscodeshift");
const fs = require('fs')
const value = `
import { Button, Input } from 'element-ui';
`;
const root = jf(value);
root
.find(jf.ImportDeclaration, { source: { value: "element-ui" } })
.forEach((path) => {
const { specifiers } = path.node;
specifiers.forEach((spec) => {
if (spec.imported.name === "Button") {
spec.imported.name = "Select";
}
});
});
consoloe.log(root.toSource())
打印结果
// import { Select, Input } from 'element-ui';
基于AST实现treeShaking
treeShaking 原理
- 从入口文件出发,找出所有它读取的变量,找一下这个变量是在哪里定义的,对所有的 CallExpression 和 IDentifier 进行检测。因为 CallExpression 代表了一次函数调用,IDentifier 代表了一个变量的取值。
- 把定义语句包含进来,而无关的代码一律抛弃,代码链接,注意:仅仅为了体现treeshaking的实现原理。