Turbopack Dev が安定版になりました
長い道のりでしたが、next dev --turbo が安定版となり、開発体験を高速化する準備が整ったことを発表できることを嬉しく思います。私たちは vercel.com、nextjs.org、v0、そして他のすべてのアプリケーションでこれを使用して反復開発を行い、素晴らしい結果を得ています。
背景
8年前のリリース以来、Next.js は週末の趣味プロジェクトから洗練されたエンタープライズアプリケーションまで、あらゆるものの構築に使用されてきました。Next.js が最初にリリースされた時、webpack はフレームワークのバンドリング基盤として明らかに最良の選択でしたが、時間が経つにつれて現代のWeb開発者のニーズに追いつくのに苦労するようになりました。
私たちのコミュニティは、ルートの読み込み、コード変更の反映、本番ビルドのデプロイを待つ間の反復開発が非常に遅いことを痛感し始めました。私たちは webpack の最適化に多くの時間と労力を投資しましたが、ある時点で、投入した労力に対して十分な改善が得られていないと感じました。
新しいバンドラーの要件
私たちは、現在本番環境で稼働している多くの Next.js アプリケーションと、React Server Components のような計画中の将来のイノベーションの両方をサポートできる新しい基盤が必要でした。
この新しいバンドラーの要件は以下の通りでした:
- 破壊的変更を最小限に抑える
- App Router と Pages Router の両方をサポート
- あらゆるサイズのコードベースでより高速なコンパイル時間
- 本番環境に近い開発ビルド
- 高度な本番最適化(モジュール内でのツリーシェイキングなど)
- Node.js とブラウザのような複数環境をサポートするモジュールグラフ
- メンテナーと上級ユーザー向けの完全な可観測性
当時の既存ソリューションをすべて評価した結果、それぞれに私たちの要件と目標に合わないトレードオフがあることがわかりました。Next.js が今日必要とすることを正確に実現し、明日必要となるものを構築・実験できるよう、ロードマップを所有するために、ゼロから設計することが理にかなっていました。
これが Turbopack を作成する動機でした。
パフォーマンス結果
私たちは開発体験の最適化から始め、それが今日安定版としてリリースするものです。Vercel のアプリケーションで Turbopack を広範囲にドッグフーディングし、開発者の反復速度を顕著に改善しました。
例えば、大規模な Next.js アプリである vercel.com では、以下の結果を確認しています:
- ローカルサーバー起動時間が最大 76.7% 高速化
- Fast Refresh でのコード更新が最大 96.3% 高速化
- キャッシュなしでの初期ルートコンパイルが最大 45.8% 高速化(Turbopack にはまだディスクキャッシュがありません)
ハイライト
より高速なルートの初期コンパイル
コミュニティから最も多く聞かれた問題の一つは、開発環境でルートの読み込みに時間がかかりすぎることで、これは webpack のコンパイル速度に起因していました。
Next.js は必要になる前にすべての可能なルートをコンパイルすることを避けるため、オンデマンドでルートをコンパイルします。これにより初期起動を高速に保ち、メモリ使用量を低く抑えますが、それでも単一ページの読み込みを待つ間に足踏みすることがありました。
webpack と Turbopack の違い
webpack は複数の環境に対する出力を生成するグラフの作成をサポートしていないため、現在の Next.js では webpack で少なくとも2つの別々のコンパイラ(サーバー用とブラウザ用)を実行する必要があります。
Turbopack では、複数のコンパイラを実行し、それらを調整するオーバーヘッドを除去することを目指しました。解決策は、コンパイラに複数の異なる出力ターゲットを認識させることでした。内部的には、これらはターゲット「トランジション」と呼ばれます。
並列化の改善
webpack と Turbopack のもう一つの大きな違いは、Turbopack が複数の CPU にわたって作業を並列化できることです。一方、webpack では SWC を使用した TypeScript / JavaScript 変換ステップのみが並列化されます。
Turbopack は Rust で書かれており、同じ制限がなく、最初から並列化を念頭に置いて構築されました。
より高速な Fast Refresh
Fast Refresh は、ブラウザで現在見ているルートに変更を伝播するためにバンドラーが使用するシステムで、Hot Module Replacement(HMR)と呼ばれることもあります。
webpack では、特定数の JavaScript モジュールに達すると Fast Refresh のパフォーマンスに限界があることがわかりました。約 30,000 モジュールで、変更が小さくても、コード変更には一貫して少なくとも 1 秒のオーバーヘッドがありました。
私たちは、インクリメンタルビルドはローカル変更のサイズのみでスケールすべきで、ルートやアプリケーションのサイズではないと考えています。
これに対処するため、非常に細かい作業の再計算を可能にする Turbopack の基盤を優先しました。この取り組みは基盤ライブラリである Turbo Engine となり、自動的な需要駆動型インクリメンタル計算アーキテクチャを使用して、大規模な Next.js と React アプリケーションの対話的なホットリロードを数十ミリ秒で提供します。
高度なトレーシング
Next.js の採用が年々拡大するにつれ、特にコンパイラのパフォーマンスとメモリ使用量に関連する GitHub で報告された問題を再現することがますます困難になりました。
Turbopack では、最初からインストルメンテーションを設計することができました。Turbo Engine にインストルメンテーション層を実装し、個々の関数のタイミングを収集できるようにしました。
新しい高度なトレーシングにより、遅延とメモリ使用量を深く調査するために必要なすべての情報が得られます。完全なコードベースではなく、トレースのみが必要です。
トレースビューアーの使用
以下の手順で Turbopack トレースを生成できます:
- トレースを生成する
next internal turbo-trace-server .next/trace-turbopack を使用してトレースを検査するサーバーを起動
トレースビューアーの簡単な動画概要も利用可能です。
コンパイル時間のばらつきの軽減
Next.js を webpack で使用する場合、コンパイル時間は十分に透明ではありませんでした。ある場合はページを開くのに 10 秒かかり、別の場合は 20 秒かかることがありました。
Turbopack の基盤アーキテクチャにより、コンパイル時間のばらつきがはるかに一貫性を持つようになりました。ルートのコンパイル時間は数パーセントしか変動せず、コンパイラのパフォーマンスを一貫して最適化できます。
本番環境により近い開発ビルド
webpack でコンパイル速度を最適化するために、開発環境と本番環境が異なる結果となるトレードオフを受け入れる必要がありました。
それらのトレードオフの例として、ページにスタイルを注入し、ページをリロードすることなく Fast Refresh を可能にする style-loader の使用があります。しかし、これは開発環境でスタイルが JavaScript によって注入されることを意味し、スタイルなしコンテンツのフラッシュを引き起こします。