Alex
深度解构 JS 工链:从铁三角割据到 Rust 大一统
- javascript
- typescript
- rust
- 工程化
- 编译器
这篇文章想回答一个很多前端工程师都隐约感受到、但又不容易讲清的问题:为什么过去那套由 Babel、ESLint 和 Prettier 组成的经典工具链,正在被一批用 Rust 重写的新一代工具快速替代?
如果你正处在“业务开发越来越熟,但总觉得上不去”的阶段,那么理解这场基础设施层面的迁移,会帮助你建立一种更高维度的工程视角。因为它讨论的已经不是“怎么写页面”,而是“代码如何被解析、校验、转换、格式化,以及为什么这些能力正在被重新发明”。
0) 旧秩序:JavaScript 工链的铁三角
过去十多年里,JavaScript 世界形成了一套高度成熟、分工明确的工具链组合:
- Babel:编译器。 负责把浏览器暂时不认识的语法翻译成它能执行的 JavaScript,比如 ESNext、JSX、TypeScript 语法。
- ESLint:校验器。 负责分析代码结构,识别潜在错误,并执行团队约定的编码规范。
- Prettier:格式化器。 负责统一代码风格,不讨论逻辑对错,只追求“打印结果一致”。
这个体系之所以伟大,不在于它功能复杂,而在于它的边界极其清晰。
- Babel 关心“能不能转译”。
- ESLint 关心“写得对不对、规范不规范”。
- Prettier 关心“长得是否整齐”。
它们像流水线上的三个工位,各司其职,彼此配合,支撑起了现代前端工程化的基本盘。
1) 繁荣背后的代价:为什么旧工具链开始显得笨重
当项目规模还小时,这套组合几乎无可挑剔。但一旦进入大型仓库、多包工程、海量增量编译的场景,问题就开始暴露出来。
0) 重复解析的性能税
最核心的问题是:同一个文件,往往会被多个工具重复解析。
一次保存,Babel 解析一遍 AST,ESLint 再解析一遍,Prettier 往往也需要构建自己的语法树或中间表示。表面上看只是三个工具串起来跑,实质上却是把最贵的那一步重复做了三次。
在小项目里,这种开销不明显;但在百万行级别的代码库里,这就是构建速度和编辑器反馈延迟的来源之一。
1) 配置碎片化
第二个问题是配置地狱。
你需要维护 Babel 配置、ESLint 配置、Prettier 配置,还要处理它们之间的优先级、继承关系和规则冲突。最典型的体验就是:
- Prettier 刚把代码格式化完。
- ESLint 马上又告诉你“格式不符合规范”。
- 于是你再装一层
eslint-config-prettier去消弭冲突。
这类问题不是“不会配”,而是系统天然由多个独立工具拼起来,边界再清晰,也意味着协作成本再上升。
2) JavaScript 自身的运行时瓶颈
第三个问题更深层:很多老牌工具本身就是用 JavaScript 写的。
这带来了两个限制:
- CPU 密集型任务难以发挥极致性能。
- 大量 AST 节点分配会触发频繁垃圾回收。
当工具只处理几十个文件时,这不构成问题;但当它们需要持续服务于大仓库、编辑器实时反馈、CI 扫描和增量构建时,性能差异会被指数级放大。
2) TypeScript 到来后,铁三角的分化更明显了
TypeScript 普及后,Babel、ESLint、Prettier 虽然都“支持 TS”,但它们支持的其实根本不是一回事。
0) Babel:类型擦除器
Babel 对 TypeScript 的态度非常务实:我只把类型注解擦掉,不负责判断类型是否正确。
比如下面这段代码,Babel 可以顺利产出 JavaScript:
const name: string = 123;它并不会告诉你这里有类型错误,因为对 Babel 来说,string 只是要被移除的语法糖。
所以从本质上说,Babel 对 TypeScript 的支持,更接近“语法层兼容”,而不是“类型系统理解”。
1) ESLint:可选的类型感知分析
ESLint 本来也是单文件分析工具,但在接入 typescript-eslint 之后,它可以借助 TypeScript 编译器 API 获取类型信息,从而执行更深层的规则检查。
这意味着它不仅能看见“语法长什么样”,还可以进一步回答:
- 这个变量的真实类型是什么?
- 这个调用在类型上是否成立?
- 这里是不是把
Promise当成同步值用了?
也正因为如此,开启类型感知 lint 后,ESLint 的能力会大幅增强,但代价同样明显:更慢、更依赖完整项目上下文。
2) Prettier:只关心结构,不关心语义
Prettier 对 TypeScript 的态度最纯粹。它只关心类型写法在视觉上占了多少空间,从而决定换行、缩进和排版方式。
它不会在乎泛型是否合理,也不会在乎接口设计是否正确。它只做一件事:把代码重新“打印”成一致的样子。
这也是为什么 Prettier 很少和“正确性”挂钩,它处理的是表示层,而不是语义层。
3) Babel 和 TSC:到底谁才是真正的编译器
很多人在刚接触 TypeScript 时都会产生一个疑问:既然 tsc 能把 TypeScript 编译成 JavaScript,那为什么项目里还要 Babel、SWC,或者现在的 Oxc?
答案是:它们做的不是同一层工作。
0) Babel 的优势:快、松、插件生态强
Babel 的核心优势是“单文件模式”。
它不需要理解整个项目的类型图谱,只需要拿到当前文件,按插件链做语法转换即可。因此它天然适合:
- 处理实验性语法。
- 做 JSX、TS 之类的语法降级。
- 搭配 polyfill 策略处理浏览器兼容性。
- 在开发阶段提供快速反馈。
1) TSC 的优势:项目级的类型裁决者
tsc 的真正价值不只是“吐出 JS”,而是对整个项目的类型关系做最终裁决。
它必须理解:
- 模块之间如何引用。
- 泛型如何展开。
- 条件类型如何递归推导。
- 一个声明改动会如何影响整张依赖图。
这使得 tsc 更像一个项目级分析器,而不仅仅是语法转译器。
2) 现代工程的现实做法:分而治之
所以今天主流工程实践基本已经形成共识:
- 代码生成交给快工具。 例如 Babel、SWC、esbuild、Oxc 这一类,它们负责尽快把代码变成可运行产物。
- 类型检查交给独立进程。 例如
tsc --noEmit,只负责判断项目是否类型正确,不参与产物生成。
这背后的思想很关键:编译速度和类型正确性不必由同一个工具、同一个进程同时承担。
这正是现代前端基建开始分层的标志。
4) Rust 挑战者登场:重新定义“前端基建”
当旧工具链的问题足够清晰后,新的答案自然会出现。2026 年,最值得关注的两股力量是 Biome 和 Oxc。
0) Biome:一次解析,到处运行
Biome 想解决的不是某一个点性能不够,而是整个链路的重复劳动。
它的核心理念可以概括为一句话:一次解析,多处复用。
同一份语法树既可以服务于 lint,也可以服务于 format。这样带来的直接收益是:
- 更少的重复工作。
- 更统一的配置体验。
- 更稳定的一致性输出。
对于团队来说,这种“一体化”价值非常大,因为它减少的不是某条规则,而是整套工具之间的摩擦。
1) Oxc:以解析器为起点的高性能生态
如果说 Biome 更像“重构整套体验”,那么 Oxc 更像“从底层性能极限开始往上长”。
Oxc 最受关注的点之一,是它在 JavaScript/TypeScript 解析速度上的极致追求。解析器一旦足够快、足够稳定,它就不再只是一个解析器,而会自然向上生长为:
- linter 的基础设施;
- transformer 的基础设施;
- bundler 的基础设施;
- 新一代构建工具的核心部件。
这也是为什么大家会把 Oxc 和 Rolldown 这样的项目联系在一起看。真正重要的不是“某个工具快 20%”,而是一整条 Rust 工具链正在形成共同底座。
5) 最后的堡垒:高性能类型检查器为什么最难
如果说解析、格式化、Lint 都已经逐步被 Rust 重写,那么真正最难被攻下的堡垒,其实是 TypeScript 类型检查器。
这也是为什么业界会持续关注 stc、TypeScript-Go 等方向。
原因很简单:类型检查远不是“把语法读懂”那么直接。它要求工具能够在一个巨大的符号网络中,做出与官方 tsc 高度一致的推理结果。
这件事难在几个层面:
- 递归推导非常深。 条件类型、映射类型、分布式联合类型都可能层层展开。
- 全局依赖关系非常复杂。 一个类型声明改动,可能牵动大量下游模块。
- 兼容性要求极高。 只要行为和官方
tsc不一致,就会在真实项目里产生大量边缘问题。
换句话说,重写一个 parser 很难,重写一个 formatter 也不轻松,但重写一个和 TypeScript 官方行为高度一致、还能快得多的类型检查器,才是真正的顶级基建挑战。
6) 为什么这场演化值得业务开发者认真关注
如果你长期做业务,很容易把这些工具当成“理所当然存在的黑盒”。但当 AI 已经越来越擅长产出常规业务代码时,开发者的竞争力也在被重新定义。
未来真正稀缺的,不只是会调用框架 API 的人,而是能理解这些问题的人:
- 代码为什么会慢?
- AST 为什么重要?
- 类型系统为什么会卡住?
- 构建工具为什么总在追求更少的解析、更少的复制、更少的内存分配?
这些问题一旦想明白,你看待前端、编译器、语言设计和工程体系的方式就会完全不同。
你会意识到,所谓“底层基建”并不是离业务很远的炫技方向,而是所有工程效率、开发体验和大规模协作能力的源头。
7) 结语:向下扎根,才能继续稀缺
从 Babel、ESLint、Prettier 的铁三角时代,到 Biome、Oxc 代表的 Rust 大一统趋势,JavaScript 工链正在经历一次很典型的技术演化:
- 先通过精细分工解决“有没有”的问题;
- 再通过统一底座解决“快不快、稳不稳、复杂不复杂”的问题。
而对于开发者个人来说,这种演化同样给出了一个非常明确的信号:
如果你想突破纯业务开发的天花板,就必须开始理解那些支撑业务代码运行的底层机制。
去读编译器,去理解类型系统,去接触内存模型,去研究为什么 Rust 能在工具链层掀起这场革命。因为在这个阶段,真正的硬通货不再只是“会做功能”,而是“能建工具、能造底座、能提升整个系统的生产效率”。
向下扎根,不只是技术选择,更是职业护城河。