将 TypeScript 编译为二进制文件

一条命令就能把 main.ts 变成一个独立的原生可执行文件。目标机器上无需 Node.js,无需打包运行时,用户也无需任何安装步骤。

terminal

$ perry compile main.ts

✓ Compiled executable: main (2.3 MB)

$ ./main

Hello, World!

被统称为“编译 TypeScript”的三件事

当开发者搜索如何将 TypeScript 编译为二进制文件时,通常会遇到三种截然不同、却共用同一个说法的技术:

  • 转译。 tsc、SWC 和 esbuild 将 TypeScript 转换为 JavaScript。输出的代码仍然需要 Node.js、Bun 或浏览器才能运行,这个过程完全不涉及二进制文件。
  • 运行时内嵌。 bun build --compile deno compile 以及 Node.js 的单文件可执行应用(SEA)会把你打包好的 JavaScript 与完整的运行时 拼接在一起。你确实得到了单个文件,但引擎也跟着一起打包了进去,并且 每次进程启动时你的代码依然要被解析并 JIT 编译。
  • 提前原生编译。 这正是 Perry 所做的事。TypeScript 先由 SWC 解析,随后解析类型、对 泛型进行单态化,再由 LLVM 生成机器码。链接器产出的是一个普通的可 执行文件——与 Rust、Go 或 C++ 工具链产出的是同一类产物。二进制文件 里完全没有 JavaScript 引擎。

由于没有引擎需要启动,启动时也无需解析任何内容,Perry 编译出的二进 制文件大约在一毫秒内就能启动。这条流水线本身在 TypeScript 原生编译器 页面以及 编译器内部原理中有更详细的介绍。

二进制文件有多大?

体积取决于你引入了什么,因为只有实际用到的代码才会被编译和链接:

  • hello world 大约为 330 KB
  • 典型的 CLI 工具在 2–5 MB 之间。
  • 引入大型框架(Fastify、mysql2 等)的完整应用大约为 48 MB

作为对比:Node SEA 可执行文件本质上是 node 二进制文件本身的一份 拷贝,因此在加入你的代码之前,根据平台不同就已经约有 88–118 MB;而 经 Bun 编译的 hello world 在 macOS arm64 上约为 60 MB,在 Linux x64 上约为 100 MB,因为其中内嵌了完整的 Bun 运行时。

Perry 对比 bun build --compile 与 Node SEA

这三者都能给你一个可以直接交给别人的单一文件。除此之外它们是截然不 同的工具,各自都有其适合的场景:

Perrybun build --compileNode SEA
产出内容AOT 编译的机器码(LLVM)打包的 JS + 内嵌的 Bun 运行时注入了你打包脚本的 node 二进制文件拷贝
执行模型原生代码,没有 JS 引擎运行时 JIT(JavaScriptCore)运行时 JIT(V8)
Hello-world 大小~330 KB约 60 MB(macOS arm64)到 100+ MB(Linux/Windows)约 88–118 MB(node 二进制文件的大小)
启动时间~1 ms~10 ms~30 ms
跨平台编译10 个目标平台,包括从 Linux 交叉编译到 Windows/macOS/iOS支持——通过 --target 支持 Linux、Windows、macOS不支持——需改为为每个平台复制对应的 node 二进制文件
JS/npm 兼容性不断增长:axios、zod v4、express、fastify、hono 已可原生 编译;其余可通过可选的 V8 回退方案运行完整——因为它本身就是 Bun 运行时完整的 Node 语义;需要预先打包,在 Node 24 LTS 上仅支持 CommonJS
状态Pre-1.0稳定在 Node 24 LTS 中为“Active development”稳定级别

坦白说:如果你的应用依赖完整的 npm 生态,并且希望零兼容性风险,那么 Bun 和 Node SEA 运行的正是你已经在开发时依赖的引擎语义——这是它们的 优势所在,体积成本对你的部署来说也未必重要。Perry 走的是另一条路。 你得到的是真正的提前编译、更小的二进制文件和毫秒级启动;作为交换, 你采用的是一个 Pre-1.0 的编译器,其 JavaScript 兼容性是被测量并公 开发布的(test262:截至 v0.5.1146,String 为 79%,Array 为 72%),而不是像 V8 那样与生俱来。

详细的正面对比: Perry 对比 Bun Perry 对比 Deno。关于 npm 包如何编译,参见 真实 npm 包与一次一致性扫尾

性能对比

原生编译带来无与伦比的效率

指标PerryNode.jsBun
二进制文件大小2-5 MB~80 MB~90 MB
启动时间~1 ms~30 ms~10 ms
运行时依赖Node.jsBun
内存开销极少V8 + GCJSC + GC

基准测试结果:快最高 18 倍

Perry v0.5.279 对比 Node.js v25 — RUNS=11 中位数,Apple M1 Max(越低越好)

accumulate
18x
object create
11x
json roundtrip
5.3x
loop overhead
4.5x
math intensive
3.6x
array read
3.3x
fibonacci
3.2x
array write
2.3x
loop data dependent
1.4x
nested loops
1.0x
二进制文件大小越低越好
Perry
5 MB
Node.js
80 MB
Bun
90 MB

今天就编译你的第一个二进制文件

通过 Homebrew、APT 或 winget 安装——然后运行 perry compile main.ts