Skip to content

Stan9726/babel-plugin-exercises

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Babel-Plugin-Exercises

一个围绕 Babel 插件、AST、Parser、静态分析与源码改造的练习项目。

项目目标不是做“完整工具链”,而是用一组小而清晰的 case,把常见的 Babel 开发思路拆开练熟:

  • 如何把源码解析成 AST
  • 如何基于 visitor 做遍历、分析、校验与改写
  • 如何生成/替换节点并保持源码语义
  • 如何把 Babel 用到 lint、编译期转换、文档生成、类型检查、宏、解释执行等场景

Case 列表

作用: 在匹配到特定函数调用时,自动插入额外参数或额外调用信息,典型例子是给 console.* 注入文件名、行列号等调试上下文。

一句话思路: 遍历 CallExpression,识别目标调用,再按上下文把新节点插到前面、替换原节点,或包装成新的表达式结构。

练习重点:

  • 识别 callee 并判断目标调用
  • 构造新的 AST 节点
  • 处理 JSX 场景与避免重复插入
  • 理解“分析节点上下文后再决定如何改写”

希望掌握:

  • Babel 插件最基础的 visitor 写法
  • path.insertBeforepath.replaceWith 等常用改写手法
  • 调试类源码增强的实现方式

备注: 这个 case 有多个版本,适合按难度逐步理解“同一个目标如何从简单实现演进到更完整的方案”。

作用: 扩展 parser,让源码支持项目自定义语法关键词 xxxx,并产出自定义 AST 节点。

一句话思路: 基于 Acorn 扩展 token 和语句解析分支,在 parser 层直接把新语法识别成 XxxxStatement

练习重点:

  • 理解“Babel 插件”之外,还有“Parser 扩展”这一层
  • 知道 token、关键词、语句分发的基础机制
  • 理解 AST 节点是如何从源码一步步被 parser 产出的

希望掌握:

  • 自定义语法扩展的基本路径
  • parser 与 transform 的职责边界
  • 看到一段源码时,能分清“这是解析期问题还是转换期问题”

作用: 给函数自动插入埋点调用,例如在函数体开头插入 tracker(),并在缺少导入时自动补齐 tracker 模块导入。

一句话思路: 先在 Program 里完成导入扫描/注入初始化,再统一改写各种函数节点,在函数体开头插入埋点语句。

练习重点:

  • Program.enter 做全局初始化
  • state 在多个 visitor 间传递数据
  • 同时处理 FunctionDeclarationFunctionExpressionArrowFunctionExpressionClassMethod
  • 处理箭头函数简写体改写成块语句

希望掌握:

  • 典型业务插件“先收集、再改写”的工作流
  • 导入补齐、函数注入、跨 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 这类工具在底层思维上的相通之处

包含的规则:

eq-operator-lint

作用: 检查 == / != 的使用,提示优先改为严格相等比较。

一句话思路: 匹配 BinaryExpression,当操作符是宽松比较且两侧类型存在风险时记录错误。

练习重点:

  • 运算表达式检查
  • 基于节点属性做规则判断

希望掌握:

  • 最基础 lint 规则的实现套路

for-direction-lint

作用: 检查 for 循环的更新方向是否和条件方向一致,避免死循环或反向更新。

一句话思路: 从 ForStatement 的 test/update 中提取运算符,判断 </<= 应配 ++>/>= 应配 --

练习重点:

  • 同一语句多个子节点之间的关联校验
  • 从语法结构中抽取程序行为约束

希望掌握:

  • “跨字段联合判断”类规则的实现思路

no-func-assign-lint

作用: 禁止给函数标识符重新赋值。

一句话思路: 匹配 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,建议按下面顺序做:

  1. 参数插入:先熟悉最基本的 AST 遍历和节点替换
  2. 自动埋点lint:进入更像真实工程插件的场景
  3. 自动 i18n自动文档:练“分析 + 改写 + 输出文件”
  4. 类型检查依赖图:练静态分析和跨节点/跨文件信息组织
  5. 代码混淆&压缩:练语义保持下的源码优化
  6. 自定义关键词js 解释器Macro:扩展对 parser / 编译期 / 运行时 的整体理解

About

A repository for babel plugin exercises.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages