AST初探:无用代码消除。AST操作原来并不难。

359 阅读1分钟

无用代码消除

实现功能: 删除未调用的函数 删除if(false)的代码块

安装babel依赖包

yarn add @babel/parser @babel/traverse @babel/types @babel/generator

index.js 代码

const fs = require('fs');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const t = require('@babel/types');
const generator = require('@babel/generator').default;

// 读取JavaScript代码
let code = fs.readFileSync('test.js', 'utf-8');
// 使用Babel解析器创建AST
const ast = parser.parse(code);
// 创建一个空的Set用于存储被调用的函数名
const calledFunctions = new Set();
traverse(ast, {
  // 当遍历到函数调用表达式时
  CallExpression(path) {
    // 如果函数调用表达式的callee是一个标识符(即函数名)
    if (t.isIdentifier(path.node.callee)) {
      // 把函数名添加到calledFunctions集合中
      calledFunctions.add(path.node.callee.name);
    }
  },
});

traverse(ast, {
  // 当遍历到函数声明时
  FunctionDeclaration(path) {
    // 如果函数名没有在calledFunctions集合中
    if (!calledFunctions.has(path.node.id.name)) {
      // 删除这个函数声明
      path.remove();
    }
  },
});

traverse(ast, {
  // 当遍历到IfStatement时
  IfStatement(path) {
    // 如果测试条件是一个字面量,且值为false
    if (t.isBooleanLiteral(path.node.test, { value: false })) {
      // 删除这个IfStatement
      path.remove();
    }
  },
});

// 生成优化后的代码
const output = generator(ast).code;

// 输出优化后的代码
console.log(output);

test.js 被检测的文件

function usedFunction() {
  console.log('被用了');
  if (false) {
    console.log('会被消除掉');
  }
}
function unusedFunction() {
  console.log('没被用');
}
usedFunction();

执行index.js

image.png

可以看到。if (false) 代码块被消除掉了。unusedFunction也被消除掉了。