vercel-labs/scriptc · 上手攻略

  • 仓库:vercel-labs/scriptc
  • 链接:https://github.com/vercel-labs/scriptc
  • 分类:工具链 · 编译器
  • 作者:Tom
  • 更新:2026-08-10

这是什么

scriptc 是 Vercel Labs 出品的 TypeScript-to-Native 编译器,将普通 TypeScript 代码直接编译为独立的原生可执行文件(ELF/mach-O),运行时无需 Node.js 或任何 JavaScript 引擎。号称"zero-runtime TypeScript",实测 startup 仅约 2.4ms(Node.js 约 47ms),二进制大小 170–200KB(纯静态),内存 RSS 仅 1–4MB(Node.js 动辄 67–116MB)。

核心思路:静态分析 + 按需降级。scriptc 逐构造(construct by construct)判断代码能否编译为原生码——能编的编,不能编的自动降级到嵌入式 quickjs-ng 引擎(~620KB),既不默默出错,也不静默膨胀。


解决什么问题

  • CLI 工具的分发噩梦:传统 Node.js CLI 分发需要用户装 Node、npm install、找对版本。用 scriptc 编译后交付一个 170KB 的原生二进制,点开就跑。
  • 轻量脚本的冷启动问题:Node.js 冷启动 40ms+,scriptc ~2ms,适合对延迟敏感的脚本和 serverless 函数入口。
  • 真正的"一份代码到处跑":同一套 TypeScript,编译出 macOS ARM64/Linux x64/Windows 原生二进制,无需 Docker 或 Node 版本管理。

快速安装

# 全局安装 CLI(需要 clang,macOS 已预装 Xcode Command Line Tools)
npm install -g scriptc

# 或者用 pnpm(项目内)
pnpm add -D scriptc

依赖:clang(macOS: xcode-select --install;Linux: apt install clang 或发行版对应包;Windows: WSL 或交叉编译)。


核心用法

运行(边编译边跑)

# 编译 + 执行,输出直接打印
scriptc run fib.ts

构建(产出原生二进制)

# 构建原生可执行文件
scriptc build fib.ts && ls -la fib
# -rwxr-xr-x  178K fib   ← 独立原生二进制,约 2ms 启动

# 查看覆盖率报告(哪些代码可静态编译,哪些需要动态引擎)
scriptc coverage app.ts
#  statements analyzed 4481
#  compile statically   4451 (99%)
#  blockers:
#   ×2 functions with optional parameters as values  SC1090
#   ×1 Promise.reject                         SC2020

动态模式(含 npm 依赖)

# 默认静态编译;当代码含 npm 依赖或 any 类型时,用 --dynamic 嵌入 quickjs-ng 引擎
scriptc build app.ts --dynamic
# 产物 ~3MB(含嵌入式 JS 引擎),但依然零 Node 依赖

Native FFI(调用 C 库)

# 用 --ffi 绑定 C ABI,声明型调用系统库
scriptc build app.ts --ffi
# 参考文档:https://scriptc.dev/ffi

构建缓存

# 默认开启内容寻址缓存,只重编译变化部分
# 禁用缓存
SCRIPTC_NO_CACHE=1 scriptc build app.ts

# 指定缓存目录
SCRIPTC_CACHE_DIR=/tmp/scriptc-cache scriptc build app.ts

编译后端(可选)

# 默认 LLVM 后端;C 后端(可读、带源码注释)
scriptc build app.ts --backend c  # 产出 .scriptc/x.c 可供阅读

开发者命令

# 编译并保留中间产物(IR + C)
scriptc build x.ts --emit-ir
# 生成 .scriptc/x.c 和 x.ir.json

# 本地开发
pnpm install && pnpm build
pnpm test          # 差异测试 corpus + 诊断快照
SCRIPTC_SAN=1 pnpm test  # AddressSanitizer + RC 审计

典型适用场景

场景 为什么 scriptc 合适
轻量 CLI 工具 170KB 二进制替代 npm 全局包,用户无需装 Node
边缘函数 / CDN edge ~2ms 冷启动,适合 Vercel Edge Functions 类场景
嵌入式 / IoT RSS 仅 1–4MB,远低于 Node 的 67MB+
构建脚本(build scripts) 零依赖、跨平台,写 TypeScript 产出原生脚本
带 npm 依赖的工具 --dynamic 自动嵌入 quickjs-ng,无需 Node 运行时

坑与注意

  1. macOS ARM64 是主平台:Linux/Windows 交叉编译有专门测试 lane,但 macOS 体验最成熟;ARM Mac 优先。
  2. --dynamic 产物有 Embed:加了 npm 依赖后二进制跳到 ~3MB,仍然比 Node SEA(60–100MB)小一个数量级,但不再是"170KB 极限"。
  3. 编译器仍需运行:每次 scriptc build 都需要 Node.js 在构建机器上运行,只是产物不需要。
  4. 未支持的部分会显式报错:SC1090(optional parameter as value)、SC2020(Promise.reject)等都有精确错误码 + 重写提示,不会静默降级。
  5. 内存安全依赖 C 运行时:quickjs-ng 引擎本身不是内存安全的;scriptc 用 AddressSanitizer 做 RC 审计,但生产环境仍需注意。
  6. 整数推断和所有权分析尚未实现(Roadmap 上),追求极致数字性能的场景暂不适用。
  7. 版本标注:README 未标具体发布版本,v1.0 尚未 release(2026-08-10 状态)。⚠️ 生产使用前请自行确认 release tag。

与同类对比

特性 scriptc Bun (bundle) Go/Rust 手动重写 pkg / nexe
语言 TypeScript 原生编译 TypeScript 运行时 需重写 Node.js 打包
二进制大小 170–200KB N/A (运行时) ~1–2MB 60–100MB
冷启动 ~2ms ~10ms ~1ms ~40ms
内存 RSS 1–4MB 20–50MB 1–5MB 60–100MB
npm 生态 ✅ --dynamic
零 JS 引擎 ✅ 静态编译
成熟度 早期(v1 未 release) 稳定 稳定

一句话:如果你想用 TypeScript 写一个零依赖、分发简单的原生工具,scriptc 是目前最接近"一份 TS → 最小原生二进制"的方案;如果需要完整 Node.js 生态(网络、文件系统深度集成),Bun 或传统 Node 方案更稳。


一句话推荐结论

写 TypeScript,分发原生二进制——scriptc 把 TypeScript 编译器前端(tsc)直连到 clang,用多少编译多少,99% 的静态代码零运行时依赖,是 CLI 工具和边缘计算场景的轻量级新选择。注意 v1 尚未正式发布,生产引入前建议确认最新 release。


来源:GitHub README (https://github.com/vercel-labs/scriptc) · 官方文档 (https://scriptc.dev/ffi)