sapling_transformer 近半月开发自述
· 3 min read
为什么做这件事情
作为一个在前端深耕的工程师,工程效率,代码运行效率一直是我所关注的内容。受 solidjs 与 rust 的影响,我正在考虑是否可以有更"好"
的方式来 transfrom jsx/tsx 代码。
在这个过程中,对于一些文档性的工作,大部分我交给了ai,也包括这篇文章的 30%。一些编码工作也尝试过让 ai 编写,但是结果通常比较差,所以不做过多描述。
发生了什么
过去半个月,sapling_transformer 项目经历了多次重构和技术路线调整。项目之所以发展到当前状态,主要是因为在实际开发过程中,原有方案暴露出一系列问题,促使不得不做出改变。
技术路线调整的原因
最初采用了 oxc 及相关依赖,目的是快速实现 AST 转换。
但 oxc 方案在实际开发中暴露出多方面问题,尤其是在内存管理上。所以不再描述 oxc 方案下的变化。
- 由于 oxc 过度追求性能,放弃了平稳的内存管理库,编写相关代码时异常痛苦,文档匮乏,仅靠 ai 阅读源码,维护难度极高。
- 文档缺失,用例缺失。在 oxc 源码历史中,出现过多次 breaking change,甚至是采用不完整的方案,以至于文档老旧。
- 库的部分缺失,在使用 oxc 方案的后半段,尝试自行实现 Visitor Traverse,但在当时的架构设计下,部分关键实现缺失,以至于无法实现架构目标。
biome 方案下的变化
迁移到 biome 相关依赖后,项目的架构演进经历了四个阶段。
最初尝试直接使用 biome 的 transform 能力,但发现 biome 作为 lint/format 工具的定位,导致其转换接口无法满足语义转换的需求,实际功能受限。
为此,第二阶段自建了 Traverse 过程,试图将 solidjs transformer 按语义迁移,但由于架构设计不成熟,代码组织混乱,维护和扩展都遇到障碍。
第三阶段对 Traverse 过程进行了重构,转向 transform 架构,但实际实现仍存在缺陷,模块划分和接口设计无法支撑复杂转换流程,架构问题依然突出。如父子关系处理,transfrom 复用。
在第四阶段(当前版本),针对前三版暴露的各种问题,对第三版进行了部分重构。具体做法包括:
- 使用自定义的树遍历。自定义的树遍历,相比于高度抽象的遍历,可以更加自由的修改遍历函数,以此来支持父子关系处理
- 增加同类型节点的不同处理方式。针对 ast transfromer,存在单个语句,不同上下文情况下,输出不同结果的场景。
- transfrom 函数复用,结构的重新调整