JSConf JP

npm install Should Never Compile: Killing Native Addons

セッショントラックAEnglish

どのJavaScriptチームも、お決まりのパターンを知っています。npm installが失敗するのは、あるパッケージがnode-gypのためにPython 2を要求し、別のパッケージにはARM64用のプリビルド版がなく、さらに別のパッケージはNode.js 22にアップグレードする直前にNode.js 20のABIでコンパイルされていたためです。チームはこれを天気のように扱います。不快で、避けられない、新入社員のノートパソコンに必ずやってくるもの、と。しかし、これは天気ではありません。アーキテクチャの問題であり、そのアーキテクチャは変化したのです。

このセッションの前提は、たった一文です。npm installは決してコンパイルを行うべきではありません。コンパイルは、メンテナーのマシン上で一度だけ行われ、どこでも同じように動作する成果物として生成されるべきです。2026年現在、その成果物は既に存在します。WASI 0.2とWIT(WebAssembly Interface Types)に基づいて構築されたWebAssemblyコンポーネントです。これは、RustライブラリとJavaScript関数を、生成されたTypeScript型と接着剤コードなしで組み合わせることができる、言語に依存しない型付きコントラクトです。これは提案ではなく、既に提供されている技術です。 Cloudflare Workersは本番環境でコンポーネントをリンクし、Bytecode Allianceのwasi:http、wasi:filesystem、wasi:cliインターフェースは安定しています。

ライブデモでその有効性を示します。Rustのimageクレート(Rustエコシステムで主流の画像処理ライブラリ)をcargo-componentで単一のコンポーネントにコンパイルし、jcoでTypeScriptバインディングを生成し、同じ未修正の成果物を3つの環境で実行します。Node.jsサービス、Bunテストスイート、そしてCloudflare Workerです。Cloudflare Workerでは、デプロイ時にWITインターフェースを介してJavaScriptレスポンスフォーマットコンポーネントと組み合わされます。node-gypも、プリビルドマトリックスも不要で、完全な型安全性が確保されています。デモリポジトリは公開されており、その日の午後に再現可能です。そして、ここからが本題です。「WASMで書き直せ」というアドバイスは、具体的な数値が伴って初めて意味を持ちます。

5つのワークロードカテゴリを、同等のネイティブN-APIアドオンと比較してベンチマークしました。画像リサイズは、WASM SIMDを使用した場合、ネイティブスループットの15%以内で動作します。圧縮とハッシュ化はより密接に関連していますが、大規模ドキュメントのJSON解析はより広範囲にわたります。現状のギャップ(Cloudflareランタイムにおけるwasi:filesystemの不完全なカバレッジ、WITバリアントタイプにおけるjco bindgenのエッジケース、OSレベルの直接I/Oに関する機能の壁など)を明確に指摘し、今すぐ移行するか、次のWASI改訂版を待つか、ネイティブのままにするか、そしてその中間的なハイブリッド戦略という意思決定フレームワークを提示して締めくくります。