Tiga hal yang disebut orang “mengompilasi TypeScript”
Ketika developer mencari cara mengompilasi TypeScript ke binary, mereka biasanya menemukan tiga teknik yang sangat berbeda namun berbagi satu kata yang sama:
- Transpilasi.
tsc, SWC, dan esbuild mengubah TypeScript menjadi JavaScript. Outputnya masih membutuhkan Node.js, Bun, atau browser untuk berjalan. Tidak ada binary yang terlibat. - Runtime tertanam.
bun build --compile,deno compile, dan Node.js Single Executable Applications (SEA) menggabungkan JavaScript yang telah dibundel dengan salinan lengkap dari runtime-nya. Anda mendapat satu file, tetapi engine-nya ikut serta di dalamnya dan kode Anda tetap di-parse dan di-JIT-compile setiap kali proses dimulai. - Kompilasi native ahead-of-time. Inilah yang dilakukan Perry. TypeScript di-parse dengan SWC, tipe diselesaikan, generic di-monomorphize, dan LLVM menghasilkan kode mesin. Linker menghasilkan executable biasa — jenis artifact yang sama seperti yang dihasilkan toolchain Rust, Go, atau C++. Sama sekali tidak ada JavaScript engine di dalam binary.
Karena tidak ada engine yang perlu dijalankan dan tidak ada yang perlu di-parse saat startup, binary Perry mulai berjalan dalam waktu sekitar satu milidetik. Pipeline-nya sendiri dijelaskan lebih dalam di halaman kompiler TypeScript native dan di struktur internal kompiler.
Seberapa besar binary-nya?
Ukurannya bergantung pada apa yang Anda sertakan, karena hanya kode yang benar-benar Anda gunakan yang dikompilasi dan di-link:
- Hello world berukuran sekitar 330 KB.
- Tool CLI tipikal berada di kisaran 2–5 MB.
- Aplikasi lengkap yang menyertakan framework besar (Fastify, mysql2, dan sejenisnya) berukuran sekitar 48 MB.
Sebagai perbandingan: executable Node SEA adalah salinan dari binary node itu sendiri, jadi ukurannya sudah sekitar 88–118 MB tergantung platform sebelum kode Anda ditambahkan, dan hello world yang dikompilasi Bun berukuran sekitar 60 MB di macOS arm64 dan sekitar 100 MB di Linux x64, karena seluruh runtime Bun ikut ditanam.
Perry vs bun build --compile vs Node SEA
Ketiganya memberi Anda satu file yang bisa Anda serahkan ke orang lain. Selebihnya, ketiganya adalah tool yang sangat berbeda, dan masing-masing merupakan jawaban yang tepat untuk situasi tertentu:
| Perry | bun build --compile | Node SEA | |
|---|---|---|---|
| Apa yang dihasilkan | Kode mesin AOT-compiled (LLVM) | JS yang dibundel + runtime Bun tertanam | Salinan binary node dengan skrip Anda yang dibundel disisipkan |
| Model eksekusi | Kode native, tanpa JS engine | JIT (JavaScriptCore) saat runtime | JIT (V8) saat runtime |
| Ukuran hello-world | ~330 KB | ~60 MB (macOS arm64) hingga ~100+ MB (Linux/Windows) | ~88–118 MB (ukuran binary node) |
| Waktu mulai | ~1 ms | ~10 ms | ~30 ms |
| Kompilasi silang | 10 target, termasuk Windows/macOS/iOS dari Linux | Ya — Linux, Windows, macOS via --target | Tidak — sebagai gantinya salin binary node per platform |
| Kompatibilitas JS/npm | Terus bertambah: axios, zod v4, express, fastify, hono dikompilasi secara native; fallback V8 opsional untuk sisanya | Penuh — inilah runtime Bun itu sendiri | Semantik Node penuh; membutuhkan pre-bundling, hanya CommonJS di Node 24 LTS |
| Status | Pra-1.0 | Stabil | Stabilitas “dalam pengembangan aktif” di Node 24 LTS |
Kerangka berpikir yang jujur: jika aplikasi Anda bergantung pada ekosistem npm secara penuh dan Anda menginginkan risiko kompatibilitas nol, Bun dan Node SEA menjalankan persis semantik engine yang sudah Anda kembangkan — itulah kekuatan mereka, dan biaya ukuran mungkin tidak menjadi masalah untuk deployment Anda. Perry menawarkan trade-off yang berbeda. Anda mendapat kompilasi ahead-of-time sejati, binary kecil, dan startup dalam hitungan milidetik; sebagai gantinya Anda mengadopsi kompiler pra-1.0 yang konformansi JavaScript-nya diukur dan dipublikasikan (test262: String 79%, Array 72% per v0.5.1146) alih-alih diwariskan dari V8.
Perbandingan head-to-head mendetail: Perry vs Bun dan Perry vs Deno. Untuk cara paket npm dikompilasi, lihat paket npm nyata dan sapuan konformansi.