一个围绕 Babel 插件、AST、Parser、静态分析与源码改造的练习项目。
项目目标不是做“完整工具链”,而是用一组小而清晰的 case,把常见的 Babel 开发思路拆开练熟:
- 如何把源码解析成 AST
- 如何基于 visitor 做遍历、分析、校验与改写
- 如何生成/替换节点并保持源码语义
- 如何把 Babel 用到 lint、编译期转换、文档生成、类型检查、宏、解释执行等场景
作用:
在匹配到特定函数调用时,自动插入额外参数或额外调用信息,典型例子是给 console.* 注入文件名、行列号等调试上下文。
一句话思路:
遍历 CallExpression,识别目标调用,再按上下文把新节点插到前面、替换原节点,或包装成新的表达式结构。
练习重点:
- 识别 callee 并判断目标调用
- 构造新的 AST 节点
- 处理 JSX 场景与避免重复插入
- 理解“分析节点上下文后再决定如何改写”
希望掌握:
- Babel 插件最基础的 visitor 写法
path.insertBefore、path.replaceWith等常用改写手法- 调试类源码增强的实现方式
备注: 这个 case 有多个版本,适合按难度逐步理解“同一个目标如何从简单实现演进到更完整的方案”。
作用:
扩展 parser,让源码支持项目自定义语法关键词 xxxx,并产出自定义 AST 节点。
一句话思路:
基于 Acorn 扩展 token 和语句解析分支,在 parser 层直接把新语法识别成 XxxxStatement。
练习重点:
- 理解“Babel 插件”之外,还有“Parser 扩展”这一层
- 知道 token、关键词、语句分发的基础机制
- 理解 AST 节点是如何从源码一步步被 parser 产出的
希望掌握:
- 自定义语法扩展的基本路径
- parser 与 transform 的职责边界
- 看到一段源码时,能分清“这是解析期问题还是转换期问题”
作用:
给函数自动插入埋点调用,例如在函数体开头插入 tracker(),并在缺少导入时自动补齐 tracker 模块导入。
一句话思路:
先在 Program 里完成导入扫描/注入初始化,再统一改写各种函数节点,在函数体开头插入埋点语句。
练习重点:
Program.enter做全局初始化state在多个 visitor 间传递数据- 同时处理
FunctionDeclaration、FunctionExpression、ArrowFunctionExpression、ClassMethod - 处理箭头函数简写体改写成块语句
希望掌握:
- 典型业务插件“先收集、再改写”的工作流
- 导入补齐、函数注入、跨 visitor 共享状态
- 插件如何对真实业务代码做无侵入增强
作用:
自动提取源码中的字符串,替换为 intl.t(...) 调用,并在编译期生成语言资源文件。
一句话思路: 遍历字符串、模板字符串和 JSX 文本,跳过不该处理的节点,记录文本 key/value,再把原文本替换成国际化调用。
练习重点:
- 多种文本节点的统一处理
- JSX 属性、JSX 文本、模板字符串的差异
pre/post生命周期与file.set/get- 编译期副产物输出,例如生成文案资源文件
希望掌握:
- Babel 在“分析 + 改写 + 产物输出”场景中的完整链路
- 如何设计跳过规则和注释控制
- AST 改写如何与工程化资源生成结合
作用: 从函数、类、参数、返回值和注释里提取结构化信息,生成 Markdown API 文档。
一句话思路:
遍历声明节点收集类型和注释信息,整理成中间数据结构,最后在 post 阶段渲染成文档文件。
练习重点:
- 从 AST 中提取函数/类签名
- 结合 TypeScript 类型注解与 JSDoc 注释
- 将分析结果沉淀为文档模型再输出
- 把“源码理解”转换成“可消费文档”
希望掌握:
- Babel 不只做代码转换,也能做静态文档生成
- 类型信息、注释信息、结构信息如何汇总
- 从 AST 走向中间表示和最终产物的思路
作用: 实现几个小型 lint 规则,用 Babel AST 做静态检查并输出定位清晰的错误信息。
一句话思路: 在遍历过程中匹配违反规则的节点,收集错误,最后统一通过回调返回检查结果。
练习重点:
- 使用
buildCodeFrameError生成可读错误 - 把 AST 条件判断转成 lint 规则
- 理解“只分析不改写”的 Babel 使用方式
希望掌握:
- 静态检查类插件的写法
- 规则设计、错误收集和结果输出
- Babel 与 ESLint 这类工具在底层思维上的相通之处
包含的规则:
作用:
检查 == / != 的使用,提示优先改为严格相等比较。
一句话思路:
匹配 BinaryExpression,当操作符是宽松比较且两侧类型存在风险时记录错误。
练习重点:
- 运算表达式检查
- 基于节点属性做规则判断
希望掌握:
- 最基础 lint 规则的实现套路
作用:
检查 for 循环的更新方向是否和条件方向一致,避免死循环或反向更新。
一句话思路:
从 ForStatement 的 test/update 中提取运算符,判断 </<= 应配 ++,>/>= 应配 --。
练习重点:
- 同一语句多个子节点之间的关联校验
- 从语法结构中抽取程序行为约束
希望掌握:
- “跨字段联合判断”类规则的实现思路
作用: 禁止给函数标识符重新赋值。
一句话思路:
匹配 AssignmentExpression,查找左值绑定是否来自函数声明/函数表达式,如果是就报错。
练习重点:
scope.getBinding()的使用- 从赋值目标反查声明来源
希望掌握:
- Babel 中作用域和 binding 的基本分析能力
作用:
实现一个最小可运行的 TypeScript 类型检查练习,支持变量赋值、函数调用、泛型映射、条件类型和部分 override 检查。
一句话思路: 先把类型注解解析成可比较的类型字符串或中间结果,再在变量声明、函数调用、类声明这些节点上做规则校验并收集错误。
练习重点:
- 解析类型注解节点
- 用
scope.setData/getData保存类型别名信息 - 泛型参数映射与条件类型求值
- 将“源码层类型信息”转成“规则层比较逻辑”
希望掌握:
- Babel 也可以承载轻量级类型分析
- 从 AST 类型节点到语义类型的映射思路
- 小型静态分析器是如何逐步搭起来的
作用: 实现一个最小版压缩器,包含标识符混淆、死代码删除、常量内联、PURE 调用消除和副作用保留。
一句话思路: 一个插件负责作用域内重命名,另一个插件负责删除/内联/保留必要副作用,再组合执行得到压缩结果。
练习重点:
scope.rename()与作用域绑定- 死代码删除的判断时机
- 纯表达式、引用次数、副作用之间的权衡
- 多插件组合执行的效果验证
希望掌握:
- 压缩器背后的基础 AST 思路
- “能删什么、不能删什么”的语义边界
- 基础优化与语义保持之间的关系
作用:
从 import / export / re-export 语句中提取模块之间的依赖关系,构建模块依赖图并输出可读摘要。
一句话思路:
递归解析入口文件,遍历模块的导入导出节点,解析本地模块路径,并用 visitedModules + allModules 维护图结构。
练习重点:
- AST 遍历与文件系统递归结合
- 相对路径解析、扩展名补全、目录
index.*解析 - 区分树形展示和真实图结构
- 循环依赖与重复依赖的处理
希望掌握:
- Babel 如何与工程分析类工具结合
- “单文件 AST 分析”如何扩展到“多文件项目分析”
- 模块图、依赖图这类工具的基础实现方式
作用:
实现一个 Babel Macro,在编译期把 files('./dir') 这类调用替换成目录文件名数组。
一句话思路: 宏在编译时读取文件系统,把运行时代码替换成静态数组字面量,实现“编译期求值”。
练习重点:
babel-plugin-macros的使用方式- 宏与普通 Babel 插件的区别
- 编译期读取外部资源并注入代码
- 让运行时逻辑前移到构建阶段
希望掌握:
- 宏适合解决什么问题
- 编译期常量折叠、资源注入的基础思路
- Babel 不只处理源码,也能接入文件系统能力
作用: 实现一个最小版 JavaScript 解释器,直接执行 parser 产出的 AST,支持变量声明、函数调用、作用域链、返回值和基础表达式计算。
一句话思路:
给每种 AST 节点类型实现一个同名解释函数,由统一的 evaluate 分发执行,并用 Scope 模拟词法作用域环境。
练习重点:
- 理解 AST 不只是“拿来改”,也可以“拿来执行”
- 用解释器方式理解 Program、Block、Call、Return、Identifier 的语义
- 用作用域对象模拟变量查找和闭包
- 区分 parser、transform、runtime execution 三个层次
希望掌握:
- 从 AST 视角重新理解 JavaScript 执行过程
- visitor/dispatch 思维如何迁移到解释执行
- 对 Babel、编译原理和语言执行模型建立更深直觉
如果是第一次系统练 Babel,建议按下面顺序做:
参数插入:先熟悉最基本的 AST 遍历和节点替换自动埋点、lint:进入更像真实工程插件的场景自动 i18n、自动文档:练“分析 + 改写 + 输出文件”类型检查、依赖图:练静态分析和跨节点/跨文件信息组织代码混淆&压缩:练语义保持下的源码优化自定义关键词、js 解释器、Macro:扩展对 parser / 编译期 / 运行时 的整体理解