TypeScript zu einer Binary kompilieren

Ein Befehl verwandelt main.ts in ein eigenständiges natives Executable. Kein Node.js auf der Zielmaschine, keine gebündelte Laufzeitumgebung, kein Installationsschritt für deine Nutzer.

terminal

$ perry compile main.ts

✓ Compiled executable: main (2.3 MB)

$ ./main

Hello, World!

Drei Dinge, die Leute “TypeScript kompilieren” nennen

Wenn Entwickler danach suchen, wie man TypeScript zu einer Binary kompiliert, stoßen sie meist auf drei sehr unterschiedliche Techniken, die sich ein Wort teilen:

  • Transpilieren. tsc, SWC und esbuild verwandeln TypeScript in JavaScript. Die Ausgabe braucht weiterhin Node.js, Bun oder einen Browser, um zu laufen. Es ist keine Binary im Spiel.
  • Eingebettete Laufzeitumgebung. bun build --compile, deno compile und Node.js Single Executable Applications (SEA) hängen dein gebündeltes JavaScript an eine vollständige Kopie der Laufzeitumgebung an. Du bekommst eine einzelne Datei, aber die Engine reist darin mit, und dein Code wird bei jedem Prozessstart erneut geparst und JIT-kompiliert.
  • Ahead-of-Time-native Kompilierung. Das macht Perry. TypeScript wird mit SWC geparst, Typen werden aufgelöst, Generics werden monomorphisiert, und LLVM erzeugt Maschinencode. Der Linker erzeugt ein normales Executable — dieselbe Art von Artefakt, die eine Rust-, Go- oder C++-Toolchain erzeugt. Es steckt überhaupt keine JavaScript-Engine in der Binary.

Weil keine Engine gestartet werden muss und beim Start nichts geparst werden muss, startet eine Perry-Binary in etwa einer Millisekunde. Die Pipeline selbst wird ausführlicher auf der Seite nativer TypeScript-Compiler und in den Compiler-Interna beschrieben.

Wie groß ist die Binary?

Die Größe hängt davon ab, was eingebunden wird, denn nur der Code, den du tatsächlich benutzt, wird kompiliert und gelinkt:

  • Ein Hello World liegt bei rund 330 KB.
  • Typische CLI-Tools landen bei 2–5 MB.
  • Vollständige Anwendungen, die große Frameworks einbinden (Fastify, mysql2 und Ähnliches), liegen bei rund 48 MB.

Zum Vergleich: Ein Node-SEA-Executable ist eine Kopie der node-Binary selbst, es startet also je nach Plattform bei etwa 88–118 MB, bevor dein Code hinzukommt, und ein mit Bun kompiliertes Hello World misst rund 60 MB auf macOS arm64 und rund 100 MB auf Linux x64, weil die komplette Bun-Laufzeitumgebung eingebettet ist.

Perry vs bun build --compile vs Node SEA

Alle drei liefern dir eine einzelne Datei, die du weitergeben kannst. Ansonsten sind es sehr unterschiedliche Tools, und jedes ist für jemanden die richtige Antwort:

Perrybun build --compileNode SEA
Was es erzeugtAOT-kompilierter Maschinencode (LLVM)Gebündeltes JS + eingebettete Bun-LaufzeitumgebungKopie der node-Binary mit eingeschleustem gebündeltem Skript
AusführungsmodellNativer Code, keine JS-EngineJIT (JavaScriptCore) zur LaufzeitJIT (V8) zur Laufzeit
Hello-World-Größe~330 KB~60 MB (macOS arm64) bis ~100+ MB (Linux/Windows)~88–118 MB (Größe der node-Binary)
Startzeit~1 ms~10 ms~30 ms
Cross-Compilation10 Ziele, einschließlich Windows/macOS/iOS von Linux ausJa — Linux, Windows, macOS über --targetNein — stattdessen eine plattformspezifische node-Binary kopieren
JS-/npm-KompatibilitätWachsend: axios, zod v4, express, fastify, hono kompilieren nativ; optionaler V8-Fallback für den RestVollständig — es ist die Bun-LaufzeitumgebungVollständige Node-Semantik; erfordert vorheriges Bundling, nur CommonJS auf Node 24 LTS
StatusPre-1.0StabilStabilitätsstufe “Active development” in Node 24 LTS

Die ehrliche Einordnung: Wenn sich deine Anwendung auf das volle npm-Ökosystem stützt und du null Kompatibilitätsrisiko willst, liefern Bun und Node SEA genau die Engine-Semantik, gegen die du ohnehin schon entwickelst — das ist ihre Stärke, und die Kosten in der Größe spielen für dein Deployment vielleicht keine Rolle. Perry ist ein anderer Trade-off. Du bekommst echte Ahead-of-Time-Kompilierung, kleine Binaries und Startzeit im Millisekundenbereich; im Gegenzug nimmst du einen Pre-1.0-Compiler in Kauf, dessen JavaScript-Konformität gemessen und veröffentlicht wird (test262: String 79 %, Array 72 % Stand v0.5.1146), statt von V8 geerbt zu sein.

Ausführliche direkte Vergleiche: Perry vs Bun und Perry vs Deno. Wie npm-Pakete kompilieren, steht in Real npm packages and a conformance sweep.

Performance-Vergleich

Native Kompilierung liefert unerreichte Effizienz

MetrikPerryNode.jsBun
Binary-Größe2-5 MB~80 MB~90 MB
Startzeit~1 ms~30 ms~10 ms
LaufzeitabhängigkeitenKeineNode.jsBun
Speicher-OverheadMinimalV8 + GCJSC + GC

Benchmark-Ergebnisse: Bis zu 18x schneller

Perry v0.5.279 vs Node.js v25 — RUNS=11 Median, Apple M1 Max (niedriger ist besser)

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
Binary-GrößeNiedriger ist besser
Perry
5 MB
Node.js
80 MB
Bun
90 MB

Kompiliere noch heute deine erste Binary

Installiere mit Homebrew, APT oder winget — dann perry compile main.ts.