Scriptc 解説 — TypeScriptをネイティブバイナリ化
Vercel Labs が公開した scriptc は、通常のTypeScriptをNode・V8を含まないネイティブ実行ファイルにコンパイルするツール。静的コンパイルと dynamic モードの3階層、公称の起動時間とバイナリサイズ、Bun/Deno/Node SEA との違いを整理します。
scriptc は、通常のTypeScriptをJavaScriptエンジンを含まないネイティブ実行ファイルにコンパイルするツールである。Vercel Labs が Apache-2.0 で公開し、2026年7月27日にHacker Newsのフロントページに載って一気に注目を集めた。方言や独自アノテーションは不要で、本物のTypeScriptコンパイラで型チェックしたうえでネイティブコードを生成する点が特徴である。
何が新しいのか — 3階層のコンパイルモデル
TypeScriptを単一実行ファイルにする手段は Node SEA や Bun / Deno の compile が先行しているが、いずれもバイナリの中にJavaScriptエンジンを同梱する方式である。scriptc はそこを分岐させ、コードを3つの階層に振り分ける。
- 静的コンパイル(既定): TypeScriptを直接ネイティブコードへ。バイナリにエンジンは入らない
- dynamic モード(--dynamic でオプトイン): 静的化できない部分だけを、同梱した QuickJS(約620KB)で実行する。npmパッケージが配布しているJSや any 型のコードが対象
- 拒否: どちらでも扱えない構文はビルド時にエラーコードと書き換え案つきで落とす
3つ目の「黙って誤コンパイルせず、ビルド時に落とす」設計が実務上は重要である。加えて scriptc coverage コマンドで、対象コードのどこが静的にコンパイルされ、どこがエンジン頼りになるかをレポートできる。
静的にサポートされる範囲
「エンジンなし」と聞くと使える範囲が極端に狭いように思えるが、リポジトリが挙げる静的サポート範囲は言語機能・標準ライブラリともに広い。
| 区分 | 静的にサポートされるとされる範囲 |
|---|---|
| 言語機能 | クラスと継承、クロージャ、ジェネリクス、async/await、try/catch/finally、分割代入、テンプレートリテラル、正規表現 |
| 標準ライブラリ | 文字列、配列、Map、Set、JSON、Math、TypedArray、Error 階層 |
| Node API | fs(同期/promises)、path、process、child_process、net / http / https / tls、dns、streams |
| Web標準 | fetch、WHATWG Streams、Headers |
| npm | Node の解決アルゴリズムで解決し、同梱の .d.ts で型チェック |
npmパッケージについては、型は解決できてもパッケージが配布している実体はJavaScriptであるため、多くの場合 dynamic モードでの実行対象になる点に注意したい。依存を持たないCLIツールほど、静的コンパイルの恩恵をそのまま受けられる。
comptime と FFI
- comptime(() => ...): コンパイラ内の隔離VMでTypeScriptをビルド時に実行し、結果をリテラルとしてバイナリに焼き込む。設定テーブルの事前計算や定数の生成に使える
- ネイティブFFI(--ffi): シグネチャだけのTypeScript宣言を C ABI 呼び出しに直接束ね、マニフェストで宣言したアーカイブ・オブジェクト・システムライブラリをリンクする
この2つがあることで、scriptc の立ち位置は「Nodeスクリプトの配布形式」ではなく、Rust や Go が担ってきた領域にTypeScriptの文法で踏み込むツールに近くなる。Rustベースの軽量デスクトップという別解についてはTauri v2 のパフォーマンスとバンドルサイズで扱っている。
公称の性能とバイナリサイズ
| 指標 | scriptc(公称) | 比較対象 |
|---|---|---|
| 起動時間 | 約2.4ms(README)/hello-world 約4ms(公式サイト) | Node 約35〜47ms |
| バイナリサイズ | 静的のみ 170〜200KB/hello-world 約320KB | Node ランタイム 約120MB |
| dynamic モード | 依存込みで約3MB | — |
| メモリ | 典型的な RSS 1〜4MB | — |
READMEと公式サイトで数値に幅があるのは測定対象のプログラムが異なるためで、いずれも公称値である。実際の判断は自分のワークロードで scriptc coverage と実測を取るのが前提になる。とはいえ「起動が数ミリ秒・数百KB」という水準は、CLIツール、Gitフック、CIの補助スクリプト、短命なサーバーレス的処理では体感差が大きい領域である。
導入と使い方
- インストール: READMEでは npm install -g scriptc が案内されている。公式サイト側はリポジトリを clone してコンパイラをビルドする Quickstart を提示している
- 前提: clang が必要(macOS では Xcode Command Line Tools に含まれる)
- 対応プラットフォーム: 主対象は macOS arm64。Linux / Windows はクロスコンパイルと差分テストで検証されているとされる
- 料金: オープンソース(Apache-2.0)で無償
| コマンド | 用途 |
|---|---|
scriptc run fib.ts | その場で実行する |
scriptc build fib.ts | ネイティブバイナリにコンパイルする |
scriptc coverage app.ts | どこまで静的コンパイルできるかを解析する |
品質保証の作り
この種のコンパイラで最も怖いのは「動くが微妙に挙動が違う」ことである。scriptc は継続的に走る2つの仕組みでそこを押さえているとしている。
- 差分テスト: 800本以上のテストプログラムを Node とネイティブバイナリの両方で実行し、stdout・stderr・終了コードがバイト単位で一致することを要求する
- メモリ安全レーン: AddressSanitizer と参照カウントの監査で、リークや use-after-free を検出する
既存の選択肢との違い
| 手段 | バイナリ内のエンジン | サイズ感 | 位置づけ |
|---|---|---|---|
| scriptc | なし(dynamic 時のみ QuickJS 約620KB) | 数百KB〜数MB | TypeScriptをネイティブコードへコンパイル |
| Bun compile | JavaScriptCore を同梱 | 数十MB | 実行環境ごと単一ファイル化 |
| Deno compile | V8 を同梱 | 数十MB | 実行環境ごと単一ファイル化 |
| Node SEA | Node ランタイムを同梱 | 数十MB〜 | 既存Nodeアプリの配布手段 |
つまり Bun / Deno / Node SEA が「配布を1ファイルにまとめる」ためのものであるのに対し、scriptc は「そもそもエンジンを持たない実行ファイルを作る」ためのものである。既存のNodeアプリをそのまま置き換える道具ではなく、依存の薄いツール類から適用先を探すのが現実的だろう。Bun を含む周辺ランタイムの実務での使い方はHono + Inertia + React を Bun と Vite でセットアップする手順でも触れている。
現時点での注意点
- 開発中のプロジェクトである。公開直後の注目段階であり、APIやサポート範囲は動く前提で扱う
- npm依存が多いコードは静的化されにくい。適用前に scriptc coverage で見積もる
- 主対象は macOS arm64。他プラットフォームは検証方法が異なるため、本番投入前に自環境での確認が要る
- clang への依存があるため、CIイメージ側の準備が必要になる
よくある質問
scriptc は Bun や Deno の compile と何が違いますか?
Bun や Deno の compile はJavaScriptエンジン(JavaScriptCore / V8)を実行ファイルに同梱して単一ファイル配布を実現するもので、バイナリは数十MB規模になります。scriptc は既定でTypeScriptをネイティブコードへ静的コンパイルし、バイナリにエンジンを含めません。静的化できない部分がある場合のみ dynamic モードで約620KBのQuickJSを同梱します。目的が配布形式の簡略化なら前者、起動時間とサイズを詰めたいなら後者が近い選択肢になります。
既存のNode.jsアプリをそのまま変換できますか?
npmパッケージへの依存が多いコードは、パッケージが配布しているのがJavaScriptであるため dynamic モードでの実行対象になりやすく、静的コンパイルの利点が薄れます。まず scriptc coverage でどの程度が静的にコンパイルできるかを確認し、依存の薄いCLIツールやスクリプトから試すのが現実的です。
独自の構文やアノテーションを覚える必要はありますか?
必要ありません。方言ではなくNodeで動かしているものと同じTypeScriptを対象とし、型チェックには本物のTypeScriptコンパイラを使うとされています。扱えない構文はビルド時にエラーコードと書き換え案つきで拒否される設計です。
料金はかかりますか?
Apache-2.0 ライセンスのオープンソースとして公開されており、利用料はかかりません。Vercel Labs は同社の実験的プロジェクトを公開する枠組みで、Vercel のホスティング契約とは独立して利用できます。
Windows や Linux で使えますか?
公式には macOS / Linux / Windows がサポート対象とされていますが、主対象は macOS arm64 で、Linux と Windows はクロスコンパイルと差分テストによって検証されているという位置づけです。開発中のプロジェクトでもあるため、本番用途では自分の対象プラットフォームで実際にビルドと動作確認を行ってから判断するのが安全です。
まとめ
scriptc の要点は「TypeScriptの文法のまま、エンジンを含まない数百KBのバイナリを作る」ことにある。静的・dynamic・拒否の3階層と scriptc coverage によって、どこまで静的化できたかが可視化される設計は、この種のツールにありがちな不透明さを避けている。現時点では開発中のプロジェクトであり、依存の多いアプリの一括置き換えには向かない。まずは依存の薄いCLIツールやCI補助スクリプトで、起動時間とサイズの差を実測してみるのが妥当な入り口だろう。
この記事に関連する無料ツール(登録不要・その場で結果)
お気軽にご相談ください
お問い合わせ