Cloudflare 与 VoidZero 把 TypeScript 编译器移植到了 Rust
tsrs 在四个真实项目上比 TypeScript 7.0 快 3.8 到 8.1 倍,峰值内存只剩两成左右。它不做 fork,跟着 TypeScript 团队的决定走,并借 Vinext 那套 agent 流程与上游保持同步。
中文
复制

Cloudflare 和 VoidZero 正与 Owner.com 的 Max Schwenk 合作开发 tsrs——TypeScript 编译器的 Rust 移植版。我们与 TypeScript 团队紧密协作推进这项工作,并将 tsrs 作为 Oxc JavaScript 编译器工具链 的一部分进行孵化。
我们的目标是让开发者少花时间等代码检查,多花时间写代码。让 TypeScript 更快、更省内存,也有助于把完整的开发环境带到更多地方,包括直接搬进浏览器。
需要说明的是,我们没有 fork TypeScript。我们认为这门语言的设计和方向应当完全由 TypeScript 团队掌控。他们始终保持着长期愿景,同时引导 TypeScript 在整个 JavaScript 社区中普及。我们不想改变这一点。
TypeScript 团队在很多事情上推进得相当快,但对某些特性,他们可能会花上数年时间有意探索各种方案、做原型,然后才选定正确的实现。Rust 移植必须紧跟这些决策,否则最终会分崩离析、变得不兼容。我们必须严格以原始实现为准来保持 TypeScript 语言不变——而它应该是什么样子,应当只由 TypeScript 团队来决定。
性能与内存改进
我们 Rust 版 TypeScript 移植的早期基准测试结果很乐观:在类型检查 worker 数量相同的情况下,tsrs 比 TypeScript 7.0 快最多 8 倍,内存占用减少约 70%:

如你所见,TypeScript 的下一个版本已经带来大量性能改进,使 TypeScript 7.1 beta 比 TypeScript 7.0 快最多 2.5 倍。其中一些优化是从 tsrs 上游合并过来的,我们还希望能找到更多。
你可能已经看过近期各种 TypeScript 移植版本的基准测试,它们给出了各式各样的性能数据,这往往是因为相比 TypeScript 的默认设置,它们使用了更大的机器规格和不同的选项。我们与 TypeScript 团队合作,确保上述基准测试比较的是相同的配置。
默认情况下,tsrs 附带一套根据机器规格自适应的配置,它会占用更多内存,但速度更快:

试用 tsrs
TypeScript in Rust 的目标是忠实移植 TypeScript。你可以从 npm 安装 tsrs 包来试用实验版本:
npm install tsrs
npx tsrs
为什么是现在?
这些年,把 TypeScript 移植到其他语言的尝试不少。由于复杂度太高,只有一次成功了:TypeScript 团队把 TypeScript 从 JavaScript 移植到了 Go。
但如今,前沿 AI 模型几乎可以独立完成大规模移植,只需几天。我们已经见到 slopforks、忠实移植,以及用 Rust 或 C++ 完全重新设计架构的 TypeScript 版本。显然,人们对更快的 TypeScript 有需求。
为什么是 Rust?
你可能会想:“TypeScript 的 Go 移植版已经比之前用 TypeScript 写的版本快了 10 倍,内存效率也高得多。这还不够吗?”
但不只是速度的问题。Rust 有一些独特的优势:能在 WebAssembly 中运行。Rust + Wasm 一直是个强组合,原因之一在于 Rust 语言设计的底层特性。把 Go 程序编译到 Wasm 时,必须把 Go 的垃圾回收器一起编译进去。而 Rust 的内存管理模型让 WebAssembly guest 与 host 之间的内存交互变得直接。这正是 Rust 更适合 WebAssembly 场景的关键原因之一:内存效率。
Cloudflare Workers 支持 Wasm 已经很久了。就在几周前,我们宣布在 Workers 中原生支持 Rust,靠的是 wasm-bindgen 新增的 Emscripten target。当你在 Workers 上以紧密循环运行整套软件构建和部署系统时,小内存占用的好处很快就会显现。这意味着你可以把这些工作负载跑得足够高效,以至于过去无法运行完整封闭开发系统的环境,现在也能跑了。
再结合 agent,就有了新的可能:你现在可以在 Cloudflare 上完全沙箱化的环境里端到端运行一套开发工具链。而借助 Wasm,你也可以在浏览器客户端、嵌入式设备或 IoT 应用中安全地运行这些环境。
tsrs 的移植版本将如何维护?
首先,我们正在与 Theo Browne 合作,把 tsc-rs 和 tsrs 合并成一个包,支持 TypeScript 的全部特性,包括 Language Server Protocol(LSP)和 content mapper。其次,在让 Vinext 与上游 Next.js 保持同步这件事上,我们已经积累了不少成功经验。具体做法写在最近的一篇博客文章里:
每天早上,一个 agent 会审查变更、拉取 diff,并为任何可能影响 Vinext 的问题开跟踪 issue。每天晚上重新生成兼容性矩阵,用 Next.js 的测试套件跑 Vinext。当某个测试或 issue 暴露出差距时,agent 现在能够定位两个代码库中对应的改动、构造复现、移植相关测试并提交修复。
我们会把同样的流程用在 TypeScript 上,同时格外小心,不引入与上游 TypeScript 行为不一致的地方。遇到性能改进时,我们会尝试回馈到 TypeScript Go 代码库,让所有人都受益。
最后,我们清楚目前与上游 TypeScript 还存在一些差异,比如诊断信息的输出顺序。我们的目标是在发布稳定版之前把这些差异降到最低。
下一步
Cloudflare 已经是许多支撑 JavaScript 生态的免费开源 Rust 工具的所在地,比如 Vite、Rolldown、Oxlint 和 Oxfmt。有超过 1000 万开发者在 Cloudflare 上构建应用,我们非常在意让底层开发者工具链更快、更可移植、更容易在更多环境中运行。我们很期待试验把 tsrs 更深入地集成进我们的技术栈,例如用于 Oxlint 的类型感知 lint 规则。
和 Vinext 一样,我们的目标是让 tsrs 成为一个维护良好、健康的开源项目,同时不妨碍 TypeScript 本身。Oxc 团队已经开始重构代码库,让它更快、占用内存更少、更易维护。我们知道 TypeScript 团队对此很重视——他们正在试验 tsc 的内存和性能改进。我们期待与 TypeScript 团队和 JavaScript 社区合作,共同打造最好、最快的 TypeScript 实现。