webpack ast 语法分析

148 阅读1分钟

webpack ast 语法分析

什么是ast ?

abstract syntax tree,抽象语法树,

ast使用场景:

  • 语法解析,检查
  • 代码格式化,高亮,错误提示,自动补全;
  • Babel -> Es6
  • 代码压缩,混淆代码
  • 可以编写那些具体有独特语法特征的高级框架,Vue React
graph LR
    A[源代码] --> B[抽象语法树]
    B --> C[遍历语法树上的各个节点]
    C --> D[对语法树进行修改转换]
    D --> E[新的语法树]
    E --> F[根据新的语法树生成的源代码]
    classDef default fill: #fff, stroke: #333, stroke-width: 4px; 

分词(tokenize)

将一行行的代码,变成一个个的token,然后构建抽象语法树,所谓的token,是指在语法上不可能再分,最小的单个字符或者字符串 esprima官网 在线拆分 1+2=3

image.png

将function的驼峰命名转换成下下划线命名

需要使用到的库

  • esprima : 解析器,将源代码转换成ast
  • estraverse : 遍历器,用来遍历ast
  • escodegen : 生成器,将ast转换成源代码

正则方法

str.replace(/([A-Z])/g, (a) => `_${a.toLowerCase()}`)

源代码

function weWantMoney() {
}
npm init -y
npm i esprima estraverse escodegen -D
// input.js
function weWantMoney() {
    console.log('$$$')
}
 // index.js
const esprima = require('esprima');
const estraverse = require('estraverse');
const escodegen = require('escodegen');
const fs = require('fs');
const inputSource = fs.readFileSync('./input.js', 'utf-8').toString();

// 生成ast
const astTree = esprima.parseModule(inputSource);
console.log('** print astTree **', astTree)

// 遍历ast
estraverse.tranverse(astTree, {
    enter(node) {
        if (node.type === 'FunctionDeclaration') {
            node.id.name = node.id.name.replace(/([A-Z])/g, (a) => `_${a.toLowerCase()}`)
            console.log('** enter **', node.id.name)
        }
    },
    leave(node) {
        console.log('** leave **')
    }
})

// 生成源代码
const outputSource = escodegen.generate(astTree);
fs.writeFileSync('./output.js', outputSource)
console.log('** outputSource **', outputSource)

API摘要:

  • esprima.parseModule 将源代码解析成ast
  • estraverse.tranverse 遍历ast
    • enter 进入节点
      • node.type 参数node FunctionDeclaration
      • node.id.name 节点名称
    • leave 离开节点
  • escodegen.generate

总结: 抽象语法树(AST)在代码处理中的应用

在软件开发中,抽象语法树(AST)就像是编程语言的蓝图,帮助我们深入理解代码的结构和逻辑。 AST将源代码转换为一种树状结构,每个节点代表代码中的一个语法元素,如变量、函数、表达式等。 这种结构使得我们可以像建筑师一样,精确地分析、修改和生成代码。

解析与构建

首先,esprima作为解析器,将源代码解析成AST。这类似于将一幢建筑物分解成砖块和构件,使得我们可以逐个检查和分析每个部分。例如,将源代码 function weWantMoney() { console.log('$$$') } 解析为AST,我们可以清晰地看到函数声明、函数体等结构。

遍历与修改

接下来,estraverse作为遍历器,帮助我们遍历AST的每个节点。这就像在建筑工地中,逐一检查每个构件的质量和位置。 在遍历过程中,我们可以对特定类型的节点进行修改。例如,将函数名从驼峰命名转换为下划线命名。 通过正则表达式 str.replace(/([A-Z])/g, (a) =>_${a.toLowerCase()}),我们可以轻松地将 weWantMoney 转换为 we_want_money

生成与输出

最后,escodegen 作为生成器,将修改后的AST重新生成为源代码。这类似于将分解后的构件重新组装成一幢完整的建筑物。通过 escodegen.generate(astTree),我们可以得到修改后的源代码 function we_want_money() { console.log('$$$')},并将其保存到文件中。

实际应用

这种技术不仅适用于简单的语法转换,还能用于复杂的代码优化和框架开发。 例如,Babel通过AST将ES6代码转换为ES5代码,确保代码在旧版浏览器中的兼容性。 Vue和React等高级框架也利用AST来解析和生成模板代码,提升开发效率和代码质量。 通过AST,我们可以像外科医生一样精确地操作代码,确保每个部分都符合预期。这种强大的工具不仅提升了代码的可读性和一致性,还为自动化代码重构和优化提供了坚实的基础