
2026/01/21 3:49
**Turbopack:構築量を削減し、より高速に実現**
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
要約
Turbopack は Next.js の新しいデフォルトバンドラで、瞬時のビルドと大規模なワークロードでも高速な React Fast Refresh を実現するように設計されています。その増分アーキテクチャは、10 年以上にわたる研究から構築された細粒度キャッシュに依存し、Salsa、Parcel、Rust コンパイラのクエリシステム、Adapton などからインスピレーションを得ています。
Turbopack の中心には value cells (
Vc<…>) があり、個々の実行単位を表します。セルが読み取られたときにのみ依存関係が記録されるため、ディスクファイル、AST、モジュールのインポート/エクスポートメタデータ、およびチャンク情報全体でサブセル粒度の追跡が可能です。ソースファイルが変更されると、Turbopack はそれに依存する関数を「汚れた(dirty)」としてマークします;これらの関数は、ホットリロード中などアクティブなクエリに組み込まれた時点で遅延再計算されます。
2 層構造の依存関係システムがこれらの関係を追跡します:
- 一次グラフ – 関数 ↔ value cells。
- 集約グラフ – 大規模なサブグラフを要約し、各ルートはアプリケーションのエントリポイントまたはルートを表します。この集約により、エラー収集や汚れたノード探索などのクエリ時のトラバースコストが削減されます。
Next.js 16.1 以前はすべてのキャッシュがメモリ内に存在していました。16.1 リリースでは
next dev 用にオンデフォルトでファイルシステムキャッシュを追加し、依存関係と集約グラフ、および value‑cell の中間結果をディスクに永続化しました。この永続化は再起動後の高速ウォームスタートを可能にし、開発者体験を向上させつつ増分精度を維持します。
Turbopack の設計は、増分計算の複雑性とバグ潜在性に対処し、GNU Make など従来のバンドラで見られる粗粒度キャッシュの落とし穴を回避します。その結果、ビルド時間が短縮され、ホットリロードがスムーズになり、より信頼性の高いパイプラインが実現します。これらは開発者の反復速度を加速させ、広範なウェブツールエコシステムに影響を与える可能性があります。
本文
編集 → 保存 → 更新 → 待機…
コードをコンパイルするという作業は、通常「待つ」ことと同義ですが、Turbopack はキャッシュと増分計算により反復ループを瞬時のサイクルへと変換します。すべての最新バンドラが増分アプローチを採用しているわけではなく、それは意図的な選択です。増分計算は大きな複雑さを伴い、バグを招くことがあります。キャッシュには追加の追跡やデータコピーが必要で、CPU とメモリへの負荷が増します。不適切に実装されると、キャッシュ自体がパフォーマンスを低下させることもあります。
なぜ挑戦を受け入れたのか
Turbopack の成功には増分アーキテクチャが不可欠だと私たちは知っていました。Next.js の新しいデフォルトバンドラとして、インスタントビルドと「タイプしながら即座に反映される」React Fast Refresh を実現する必要があります――最大規模で最も要求の高いワークロードでも同様です。この増分設計がその核となります。
デザイン原則
-
キャッシュを念頭に置いたゼロからのアーキテクチャ
Turbopack の増分システムは、webpack のキャッシュ問題を直接経験し、10 年以上の研究成果を活かしてゼロから構築しました。Salsa(Rust Analyzer や Ruff で使用)、Parcel、Rust コンパイラのクエリシステム、Adapton などに触発されました。 -
細粒度キャッシュ
内部関数がどのように呼び出され、何を参照しているかを自動的に追跡することで、変更があった場合には最小限の結果だけを再計算します。
手動 vs. 自動増分計算
手動依存関係グラフ
GNU Make など多くのビルドシステムは明示的な依存関係グラフを宣言するよう求めます。理論上は最適ですが、エラーが起きやすく、ファイル単位で粗い粒度になりがちです。粗い粒度はキャッシュサイズを削減しますが、内部データ構造のキャッシュ機会も失います。
自動細粒度計算
バンドラはツリーシェイキングや依存関係クラスタリングのためにプログラム全体を解析します。生成されたアーティファクトはソースファイルとの多対多の複雑な関係を持つため、手動グラフでは実用的ではありません。Turbopack は関数レベルで依存関係追跡を自動化することでこれを解決します。
Value Cells – 自動キャッシュの核
- 各 value cell(Vc<…>)は、スプレッドシートセルに似た細粒度実行単位です。
- 関数がセルを読み取ると、その関数自身と読み取ったすべてのセルを依存関係として記録します。
- 依存関係は初回読み取り時にのみ登録され、トップダウンメモ化よりも細かな粒度が実現できます。
- 例:多くの value cell を持つオブジェクトが引数になると、その具体的なセルだけが変更された場合に再計算がトリガーされます。
Value cells は、ディスクファイル・AST・インポート/エクスポートメタデータ・チャンク分割やバンドリングのクラスタリングデータなど、Turbopack 内のすべてをカバーします。
ダーティプロパゲーション
- 初回実行:要求された出力(バンドル済みアセット)を根とし、ソースファイルを葉とするグラフを構築。
- ファイルシステムウォッチャーが変更されたファイルの value cell を読み取った関数を ダーティ とマーク。
- ダーティな関数を再計算すると影響を受けるセルが更新され、内容が変わらない場合は更新をスキップ。
- ダーティ状態はグラフ上で伝播し、すべての影響を受けた関数が再計算されるまで続く。
需要駆動実行 は、ダーティな関数が「アクティブクエリ」(ホットリロードされたページや本番ビルドなど)に含まれるまで再実行を遅延させます。
集約グラフ
大規模な依存関係グラフの一部を調べる必要がある操作があります:
- サブグラフがアクティブになるときにすべてのダーティノードを探す。
- エラー、警告、リント情報をサブグラフから収集する。
- サブグラフの計算完了を待つ。
細粒度キャッシュは数百万ノードに達することがあるため、集約グラフ―層状の要約を使用して走査コストを削減します。各レイヤーでより多くの関数を少ないノードにまとめ、上位レイヤーでは詳細度が下がりますが、走査すべきノードは大幅に減少します。エントリポイントやルートなど、あらゆる潜在的なアクティブクエリは集約グラフの根になります。
ファイルシステムキャッシュ
Next.js 16.1以前はすべてのキャッシュがメモリ内に留まっていました。新バージョンでは
next dev 用に ファイルシステムキャッシュ が追加され、安定してデフォルトで有効になります。これにより次のものが永続化されます:
- 依存関係グラフ
- 集約グラフ
- value cell に格納されたすべての中間結果
再起動時に
next dev はこの温かいキャッシュから復帰し、スタートアップ時間を大幅に短縮します。
永続的キャッシュの実装には、パフォーマンスと品質基準を満たすために 1 年以上の集中的な作業が必要でした。詳細は今後公開予定のエンジニアリングブログで共有します。
フィードバック & コミュニティ
Next.js の未来を共に形づくるために、ぜひご参加ください: