Vercel 的 Scriptc 将 TypeScript 编译为原生二进制,无需 Node 或 V8

Vercel Labs 的编译器默认使用静态降低,仅通过选择加入的模式嵌入 QuickJS,并拒绝无法安全转换的代码。

By · Published

Primary source: GitHub

Why it matters

Scriptc gives TypeScript developers a credible path toward tiny native CLIs and services, while exposing exactly where JavaScript's dynamic behavior still requires a runtime.

Diagram showing Vercel's Scriptc converting TypeScript into native binaries, with labeled stages for static lowering, an optional QuickJS embed, and rejected unsafe code paths.

Vercel,由 Guillermo Rauch 创立并领导,已推出 Scriptc,这是一个开源编译器,可以将普通的 TypeScript 转换为本地可执行文件,而无需在其默认静态路径生成的二进制文件中捆绑 Node.js、V8 或其他 JavaScript 引擎。该 Apache-2.0 项目于 7 月 27 日发布了 0.0.17 版本,这是过去四天开发高峰期间发布的若干版本之一。 (github.com)

发行记录显示 Chris Tate 是 Scriptc 的活跃提交者之一,尽管提供的来源并未证明他是该项目的创始人或正式负责人。Tate 的提交出现在最近的 Scriptc 活动中,工作涉及本地外部函数调用、Windows 交叉编译、Node 兼容性测试以及管理无法静态编译的 npm 包的规则。 (github.com)

Scriptc 延续了 Rauch 在 Vercel 改名之前就已开始的一个押注。他创建了用于 MongoDB 的对象建模库 Mongoose,并围绕为普通开发者提供曾经只属于大型科技公司的基础设施构建了 Vercel。Vercel 起初名为 ZEIT,专注于简化部署,随后扩展到框架、构建系统、AI 工具链和托管计算。Scriptc 将这一论点推进到部署之下、进入可执行文件本身:TypeScript 开发者应该能够保留他们的语言,同时剥离传统上附带的大部分运行时负担。 (vercel.com)

一个把动态行为显式化的编译器

Scriptc 的核心设计选择是三层执行模型。受支持的 TypeScript 被编译成本地代码。依赖于随包发布的 JavaScript 或类型为 any 的值的代码,可以在开发者显式启用 --dynamic 时通过嵌入的 QuickJS 引擎运行。不受支持的构造会在编译时失败并给出编号诊断,在许多情况下还会提供建议的重写。 (scriptc.dev)

这一限定很重要。关于 Scriptc 在其静态层生成不包含 JavaScript 引擎的二进制文件的头条声明,仅适用于其静态层。使用 --dynamic 的构建会携带嵌入式引擎,Scriptc 的资料将动态模式下的二进制体积列为大约 3 MB,而非更小的静态范围。编译器还包含一个 coverage 命令,用于报告哪些语句可以静态编译、哪些需要动态执行以及哪些会阻塞构建。

这种“静态或拒绝”的立场比传统的 JavaScript 打包工具划定了更清晰的边界。 Bun 的独立可执行文件功能 将 Bun 运行时与导入的文件和包捆绑在一起。Deno compile 将应用嵌入到 denort 中,这是一个精简的 Deno 运行时。Node 的单一可执行应用 将准备好的应用 blob 注入到 Node 二进制中。这些系统通过携带运行时来优先考虑兼容性。Scriptc 尝试证明每个受支持的构造都可以被降为本地代码,然后对其余部分拒绝处理,除非开发者选择使用 QuickJS。 (docs.deno.com)

Porffor 在技术上更为接近。它也将 JavaScript 和 TypeScript 进行预编译为 WebAssembly 或本地二进制,而不打包完整运行时。Scriptc 则在常规 TypeScript、官方 TypeScript 检查器和选定的 Node API(包括文件访问、网络、HTTP、TLS、子进程和缓冲区)上做出不同的兼容性承诺。该项目将这些能力呈现为适合命令行程序和小型服务的接口。 (porffor.dev)

基准仍以 Scriptc 的说法为准

Scriptc 表示运行了超过 800 个差异测试,在 Node 下和作为本地二进制分别执行每个语料程序,然后比较标准输出、错误和退出代码。代码库还描述了一个 AddressSanitizer 测试通道,旨在捕捉内存错误和泄漏。这些保障比演示基准要强,但它们仍然是由 Scriptc 的维护者设计并报告的测试。 (github.com)

性能数据应当谨慎解读。Scriptc 的资料描述了大约 170 KB 到 200 KB 的静态二进制、约 2 到 4 毫秒的启动时间、典型内存使用 1 MB 到 4 MB,以及动态模式下约 3 MB 的二进制体积。这些都是维护者提供的数据;所提供的页面并未给出足以将其视为独立基准的方法论。 (github.com)

Scriptc 的时间点契合了 TypeScript 市场内向本地化工具转变的更大趋势。Microsoft 于 7 月 8 日发布了以原生 Go 移植实现的 TypeScript 7.0,报告全量构建速度提升 8 倍到 12 倍。Microsoft 的工作加速了编译器和语言服务,同时仍保留 JavaScript 作为 TypeScript 的常规输出。Scriptc 迈出下一步,试图将应用程序也变为本地。 (devblogs.microsoft.com)

Vercel 进一步下移技术栈

Vercel 可以资助这一实验,而无需强制立即形成商业模式。2025 年 9 月,Vercel 完成了 3 亿美元的 F 轮融资,投后估值 93 亿美元,由 Accel 和 GIC 共同领投。Scriptc 以 Apache-2.0 许可证作为 Vercel Labs 的代码库发布。 (vercel.com)

这一方向仍然与 Vercel 从前端部署向软件创建与执行周边基础设施扩展的路径一致。Scriptc 从另一个端点切入,为开发者提供了一种从 Vercel 产品和客户基础中常用的语言生成小型、可移植可执行文件的方式。

该项目最艰巨的任务将是维持它所划定的边界。JavaScript 的许多有用性来自于动态行为、npm 兼容性和运行时反射。每一个不受支持的特性都会带来压力,要么扩展 Scriptc 的本地降级,要么把更多代码通过 QuickJS 运行,这会削弱小二进制的主张。编译器的拒绝代码和覆盖报告使这种权衡可见。是否有开发者接受这些限制,将决定 Scriptc 是成为 TypeScript 命令行工具和服务的实用工具,还是仅仅停留在展示可以被编译掉多少 JavaScript 的一项雄心勃勃的演示。

Reader comments

Conversation for this story loads after sign-in.