Babel 与 AST

解释 Babel 如何利用 AST 进行 JavaScript 代码的语法转换和分析。

#tech / dev / frontend #type / synthesis #status / growing #resource / javascript

[!info] related notes

Babel 与 AST

这篇笔记回答两个问题:AST 是什么,以及 Babel 如何利用 AST 完成代码转换。

一句话定义

AST(抽象语法树)是代码的结构化树形表示,Babel 通过”解析 -> 转换 -> 生成”三步利用 AST 完成 JS 语法转换。

AST 是什么

AST 是源代码语法结构的树状抽象。每个节点代表代码中的一个语法构造。

const a = 1 + 2;

对应的 AST 大致为:

VariableDeclaration
  └── VariableDeclarator
        ├── id: Identifier("a")
        └── init: BinaryExpression
              ├── operator: "+"
              ├── left: NumericLiteral(1)
              └── right: NumericLiteral(2)

Babel 三阶段

1. Parse(解析)

将源代码字符串解析为 AST。使用 @babel/parser(基于 acorn)。

源代码 -> Token 流 -> AST

2. Transform(转换)

遍历 AST,通过 visitor 模式对节点进行增删改。每个 plugin 就是一个 visitor。

// 示例:将箭头函数转为普通函数
const arrowPlugin = {
  visitor: {
    ArrowFunctionExpression(path) {
      path.replaceWith(
        t.functionExpression(null, path.node.params, path.node.body)
      );
    }
  }
};

3. Generate(生成)

将转换后的 AST 重新生成为目标代码字符串,同时生成 Source Map。

AST -> 目标代码 + Source Map

常见 Babel Plugin / Preset

  • @babel/preset-env: 根据目标环境自动选择语法转换
  • @babel/plugin-transform-arrow-functions: 箭头函数转换
  • @babel/plugin-transform-classes: class 语法转换
  • @babel/plugin-transform-runtime: 复用 helper 函数,减少产物体积

AST 的其他用途

  • ESLint:遍历 AST 检查代码规范
  • Prettier:基于 AST 重新格式化代码
  • webpack tree-shaking:基于 AST 分析静态导入导出
  • 代码压缩:基于 AST 删除无用代码

常见边界

  • AST 不包含注释、空格、换行等格式信息(除非特别配置)
  • 不同 parser 生成的 AST 格式可能不同(ESTree、Babel AST、TypeScript AST)
  • Babel 只做语法转换,不做类型检查(TypeScript 需要额外处理)

最小例子

const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const generate = require('@babel/generator').default;

const code = 'const add = (a, b) => a + b;';

// 1. Parse
const ast = parser.parse(code, { sourceType: 'module' });

// 2. Transform
traverse(ast, {
  ArrowFunctionExpression(path) {
    console.log('Found arrow function at', path.node.loc.start.line);
  }
});

// 3. Generate
const output = generate(ast, {}, code);
console.log(output.code);
创建于 2026/4/3 更新于 2026/5/27