Vercel 推出 Scriptc:TypeScript 转原生编译器,二进制文件中不含 JavaScript 引擎
Hacker News 摘要原标题:Scriptc by Vercel: TypeScript-to-Native compiler, no JavaScript engine in binary
Vercel 实验室推出的 Scriptc 是一个将 TypeScript 直接编译为原生可执行文件的编译器。它的核心特点是零运行时,生成的二进制文件中不包含 Node.js、V8 或任何 JavaScript 引擎,从而实现极小的体积和极快的启动速度。
基本功能与优势
Scriptc 可以将标准的 TypeScript 代码编译成快速的原生程序。它不需要开发者对现有代码进行修改,也不需要特殊的注解或方言。它直接使用真正的 TypeScript 编译器进行类型检查,并确保编译后的行为与 Node.js 保持逐字节的一致性。
在性能方面,Scriptc 的启动时间约为 2.4 毫秒,远快于 Node.js 的 47 毫秒,与 Zig 语言处于同一水平。生成的静态二进制文件体积仅为 170 到 200 KB,而内存占用通常只有 1 到 4 MB。
静态编译级别
Scriptc 采用显式的三层执行模式,开发者可以通过命令行工具查看代码的覆盖率和编译状态:
1. 静态编译:这是默认模式。代码被编译为原生机器码,不含引擎。
2. 动态运行:通过 --dynamic 参数启用。它会嵌入一个约 620 KB 的 QuickJS-ng 引擎,用于处理无法静态化的部分,例如 npm 依赖包中的 JavaScript 或使用了 any 类型的内容。
3. 拒绝编译:对于无法处理的内容,编译器会报错并提供具体的错误代码、代码帧及改写建议,确保不会出现静默的编译错误。
支持的语言特性与库
Scriptc 支持广泛的 TypeScript 语言特性,包括类、单继承、动态分派、闭包、泛型、异步编程(async/await)、异常处理、解构赋值、模板字符串和正则表达式。
在标准库方面,它实现了与 JavaScript 语义一致的字符串、数组、映射和集合。此外,它还涵盖了大量的 Node.js API,例如文件系统操作、路径处理、子进程、加密、网络(HTTP、HTTPS、TLS)、定时器以及事件循环。它还内置了对 fetch 和 Web 标准子集的支持。
npm 依赖与类型安全性
在使用动态模式时,Scriptc 遵循 Node.js 的算法解析 npm 包,并根据 .d.ts 文件进行类型检查。所有 JavaScript 依赖都会在构建时嵌入二进制文件,程序运行时无需读取 node_modules 目录。
为了保证正确性,Scriptc 引入了两种强制机制。一是差异化测试,通过 800 多个测试用例确保原生二进制文件与 Node.js 的输出完全一致。二是内存安全审计,在构建过程中运行地址检查器以防止内存泄漏和非法访问。
高级扩展功能
1. 编译时执行:使用 comptime 语法可以在构建阶段运行 TypeScript 代码,并将结果作为常量直接写入二进制文件。
2. 原生外部函数接口(FFI):通过 --ffi 参数,开发者可以直接将 TypeScript 声明绑定到 C 语言接口,链接外部归档文件或系统库。
3. 检查转换:在处理 JSON 解析时,Scriptc 会插入运行时验证,确保数据结构符合 TypeScript 的类型定义,并在不匹配时抛出详细的错误。
架构设计
Scriptc 的架构分为三个主要部分。编译器前端将代码转换为中间表示(IR),后端则支持 LLVM 生成机器码或生成可读的 C 语言代码。运行时部分采用 C 语言编写,包含引用计数管理、垃圾回收、基于 Fiber 的事件循环以及网络协议栈。命令行工具则提供了构建、运行和覆盖率分析等功能。