コンテンツへスキップ
ブログに戻る

2024年10月21日月曜日

Turbopack Dev が安定版になりました

投稿者

長い道のりでしたが、next dev --turbo が安定版となり、開発体験を高速化できるようになったことを発表できて嬉しく思います。私たちは、vercel.comnextjs.orgv0、その他すべてのアプリケーションで素晴らしい結果を出すために、これを使用して反復開発を行ってきました。

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にはまだディスクキャッシュがありません)。

この記事では、これらの結果をどのように達成したか、その他のハイライトとともに説明します。また、このリリースで期待できることと、次に期待できることのロードマップも明確にします。

ハイライト

ルートの初回コンパイルを高速化

コミュニティから寄せられた最大の問題の1つは、開発中にルートの読み込みに時間がかかりすぎることでした。これはwebpackのコンパイル速度に起因していました。Next.jsは、必要なときにすべての可能なルートをコンパイルする必要がないように、オンデマンドでルートをコンパイルします。これにより、初期起動が高速になり、メモリ使用量も低く抑えられますが、それでも、単一のページが読み込まれるのを待っている間にイライラすることがありました。

公平に見て、webpackのようなバンドラーは内部で多くの処理を行っています。初めてルートをコンパイルするとき、バンドラーは「エントリーポイント」から開始します。Next.jsの場合、それはpage.tsxと、そのルートに関連するすべてのファイル(layout.tsxloading.tsxなど)の組み合わせです。これらのエントリーポイントは解析され、ファイルに解決されるimportステートメントが検索され、それらのファイルはエントリーポイントと同様に処理され、このサイクルはこれ以上インポートが見つからなくなるまで続きます。このプロセスはモジュールのグラフを構築し、これにはTypeScript / JavaScriptモジュール(node_modulesを含む)だけでなく、CSSファイル(グローバルとCSSモジュールの両方)、およびnext/imageのインポートされた画像のような静的ファイルも含まれます。

すべてのモジュールが収集された後、モジュールグラフを使用してJavaScriptのバンドル、しばしば「チャンク」と呼ばれるものが作成されます。これらのチャンクは、サーバー(ビルド時またはランタイム)またはブラウザで実行されるコンパイラの出力です。

webpackは複数の環境向けの出力を生成するグラフの作成をサポートしていないため、今日のNext.jsではwebpackを使って、サーバー用とブラウザ用の少なくとも2つの別個のコンパイラを実行する必要があります。最初にサーバーモジュールグラフをコンパイルして、"use client"へのすべての参照を見つける必要があります。サーバーが構築されたら、そのグラフをたどってブラウザコンパイラ用の関連するエントリーポイントを作成します。これは別個のwebpackコンパイラであるため、クライアントとサーバーの両方で同じコードを2回解析するなど、このプロセスにはいくつかのオーバーヘッドがあります。

Turbopackでは、複数のコンパイラを実行し、それらの間で調整するオーバーヘッドを排除することに着手しました。その解決策は、コンパイラを複数の異なる出力ターゲットに対応させることでした。内部的には、これらはターゲット「トランジション」と呼ばれます。インポートをサーバーからブラウザへの、またはブラウザからサーバーへのトランジションとしてマークできます。これにより、TurbopackはServer ComponentsとClient Components、およびClient ComponentsからインポートされたServer Functionsを効率的にバンドルできます。

パフォーマンスの向上に加えて、単一パスで複数の環境を処理できる単一のコンパイラを持つことは、Next.jsで2つの別個のコンパイラプロセス間で調整する必要がなくなるため、信頼性とデバッグのメリットがあります。

webpackとTurbopackのもう1つの大きな違いは、Turbopackが複数のCPUにわたって作業を並列化できるのに対し、webpackではSWCを使用したTypeScript / JavaScript変換ステップのみが並列化される点です。

webpackはCPU間での並列化をサポートしていません。なぜなら、効果的に並列化するためには、スレッド間でデータに簡単にアクセスできる必要があるからです。webpackは、大量のJavaScriptオブジェクトを多用する方法で構築されており、これは高価なシリアル化と逆シリアル化なしにはスレッド間で簡単に共有できません。このオーバーヘッドは、多くの場合、複数のCPUを活用することによるパフォーマンス向上を打ち消してしまいます。TurbopackはRustで書かれており、同じ制限がなく、最初から並列化を念頭に置いて構築されました。

また、ファイルシステム読み書きの高速化、モジュール解決の高速化、そして副作用のないモジュールでの作業をさらにスキップすることで、パフォーマンス向上を達成しました。

大規模なNext.jsアプリケーションであるvercel.comでTurbopackを使用すると、webpackを使用するNext.jsと比較して、初期コンパイルが最大45.8%高速化することが確認されました。

Fast Refreshの高速化

Fast Refreshは、バンドラーがブラウザで現在表示しているルートに変更を伝播するために使用するシステムで、Hot Module Replacement(HMR)と呼ばれることもあります。

Next.jsには、Fast RefreshとReactを接続するより深い統合があり、コンポーネントを変更してもReactが状態を失わないようにします。

webpackでは、一定数のJavaScriptモジュールに達するとFast Refreshのパフォーマンスに限界があることがわかりました。webpackは、変更されていないモジュールであってもグラフトラバーサルと出力生成を行う必要があり、JavaScriptモジュールの量に比例してスケーリングします。

約30,000モジュールになると、コード変更は、変更が小さいかどうかにかかわらず、更新を処理するのに常に少なくとも1秒のオーバーヘッドがかかることがわかりました。たとえば、CSSファイルの色を変更するのに1秒かかることがあります。

このパフォーマンスは私たちにとって許容できるものではありませんでした。インクリメンタルビルドは、ルートやアプリケーションのサイズではなく、ローカルな変更のサイズのみでスケーリングすべきだと考えています。button.tsxが変更された場合、コンパイラは変更の影響を受けない他のモジュールや出力ファイルを再計算するのではなく、そのファイル変更に関連する作業のみを実行すればよいはずです。これに対処するため、Turbopackでは非常にきめ細かい作業の再計算を可能にする基盤を優先しました。

この取り組みは、基盤となるライブラリであるTurbo Engineとして実を結びました。これは、自動的にオンデマンドでインクリメンタルな計算を行うアーキテクチャを使用して、大規模なNext.jsおよびReactアプリケーションのインタラクティブなホットリロードを数十ミリ秒で提供します。このアーキテクチャは、webpackSalsaParcelAdapton、およびRustコンパイラのクエリシステムを含む、10年以上にわたる研究と先行技術に基づいています。

Turbopackでは、Fast Refreshの速度が変更のサイズに比例してスケーリングするようになり、その結果、vercel.comのような大規模なNext.jsアプリで、Fast Refreshによるコード更新が96.3%高速化を実現できました。

高度なトレース

Next.jsが長年にわたって普及するにつれて、GitHubで報告された問題、特にコンパイラのパフォーマンスやメモリ使用量に関連する問題を再現することがますます困難になっていることがわかりました。これは、ほとんどの人がアプリケーションコードを共有できないか、コードを共有してもデータベースやその他のセットアップが必要なため、アプリケーションが実行できないためです。

これに対処するため、Next.jsの内部にトレース機能を追加しました。これらのトレースは.nextフォルダ内のファイルに書き込まれ、アプリケーションコードは含まれません。ファイルパス、コンパイラが費やした時間、個々の変換などの他のタイミングのみが含まれます。しかし、webpackの場合、コンパイラのメモリ使用量とフレームワークまたはアプリケーションコードのメモリ使用量を明確に区別する良い方法がありませんでした。なぜなら、それらすべてが同じNode.jsインスタンスで実行されるためです。

Turbopackでは、最初から計測機能を組み込んで設計することができました。私たちはTurbo Engineに計測レイヤーを実装し、個々の関数のタイミングを収集できるようにしました。これらのトレースを拡張して、すべての関数におけるメモリ割り当て、解放、および永続化されたメモリも追跡できるようになりました。

この新しい高度なトレースにより、パフォーマンス低下とメモリ使用量を深く調査するために必要なすべての情報が得られます。完全なコードベースではなく、トレースのみが必要です。

これらの新しいトレースを処理するために、アプリケーションやトレースのサイズに関わらずパフォーマンスを維持するカスタムトレースビューアを実装しました。これは、Turbopackのパフォーマンス低下とメモリ使用量を調査するために特別に構築されたトレースビューアであり、フィードバックループを短縮することで、多くのアーリーアダプターアプリケーション全体のパフォーマンスを最適化することを可能にしました。

トレースビューアは当初内部使用向けに構築されましたが(深い技術的な掘り下げが必要な状況を想定しています)、Next.jsで自分で実行するために必要な機能は実装済みです。これらの手順を使用してTurbopackトレースを生成できます。トレースが生成されたら、next internal turbo-trace-server .next/trace-turbopackを使用してトレースを検査できるサーバーを起動できます。トレースビューアの簡単なビデオ概要はこちらで利用できます。

コンパイル時間の不安定性を軽減

webpackとNext.jsを使用する場合、コンパイル時間が十分に透過的でないことがよくあります。ある場合はページの表示に10秒かかり、別の場合は20秒かかることがあります。キャッシュが存在する場合でも、一貫した結果を出すのに十分な効果がないことがあります。キャッシュなしでのコンパイルでも、ある程度のばらつきが見られました。

Turbopackの基盤となるアーキテクチャは、コンパイル時間のばらつきがはるかに一貫していることを保証します。ルートのコンパイル時間は数パーセントしか変動せず、コンパイラのパフォーマンスを一貫して最適化することを可能にします。

本番環境に限りなく近い開発ビルド

webpackでコンパイル速度を最適化するために、開発環境と本番環境が乖離するいくつかのトレードオフを受け入れる必要がありました。これらのトレードオフの例としては、ページにスタイルを注入し、ページをリロードせずにFast Refreshできるようにするstyle-loaderを使用している点が挙げられます。しかし、これは開発中にスタイルがJavaScriptによって注入されることを意味し、スタイルなしのコンテンツが一瞬表示される原因となります。私たちはこのスタイルなしのコンテンツの一瞬の表示を回避するように対処しているため、ユーザーには見えません。別の例としては、webpackを使用するNext.jsがeval-source-mapを使用している点です。これは、すべてのコードがevalでラップされ、ソースマップがその中に含まれることを意味します。これにより、開発中にソースマップが利用可能になりますが、バンドルされたコードの検査やデバッグが難しくなるという代償を伴います。webpackはsource-mapオプションを使用して完全なソースマップを出力することをサポートしていますが、コンパイル時間とメモリ使用量に非常に大きな影響を与えます。

Turbopackでは、これらの問題をデフォルトで解決することを目指し、evalを使用せずにCSSファイルとソースマップを出力します。Turbopackは、ソースマップ仕様の比較的新しい部分であるsections sourcemapsを活用しており、これによりソースマップ出力のより効率的なマージが可能になります。以前はすべてのマッピングを1か所で生成する必要がありましたが、現在ははるかにきめ細かく生成してキャッシュできるようになりました。

TurbopackのCSS処理は常にCSSファイルを出力し、JavaScript処理と同様に、Turbopack開発ランタイムの一部であるメカニズムによって、ブラウザをリフレッシュすることなくCSSファイルを更新できます。

Turbopackを使用した開発環境で何かが機能する場合、本番環境でも同様に機能し、同じように動作すると自信を持って言えるようになりました。

最初の安定版リリース

2年前、Next.js 13でTurbopackをアルファ版として導入し、そのパフォーマンスの可能性をプレビューとして提供しました。初期の結果は有望でしたが、basePathなど多くのNext.js機能がまだ実装されておらず、基本的な使用法しかサポートしていませんでした。

翌年、私たちは不足しているNext.jsとバンドル機能の追加に注力しました。コミュニティからのフィードバックに基づき、最も一般的な反復速度の不満に対処できるように、next dev体験に完全に焦点を当てることを決定しました。昨年のNext.js Confの時点で、開発テストの90%が合格しており、Vercelの開発者はすでに日々の開発でTurbopackを使用していました。

4月には、Next.js 14.2を発表し、テストの99.8%が合格し、その後すぐに100%に達しました。それ以来、npmパッケージ、Fast Refresh、エラー位置の正確性に関するGitHubで報告された問題に対処してきました。

確かに、安定版への道のりは長い時間がかかりましたが、その主な理由は、安定性に対する高い基準を設定しているNext.jsの広範なテストスイートにあります。8年間をかけてエッジケースを発見し、Turbopackでも合格する必要のある6,599の開発テストを追加しました。さらに、Turbopackはwebpackとはまったく異なるアーキテクチャで設計されていることも要因です。単にwebpackをRustに移植する方が簡単だったかもしれませんが、私たちが達成したいパフォーマンス上の利点を引き出すことはできなかったでしょう。

Turbopackがすべてのテストに合格し、主要なnpmパッケージで検証され、アーリーアダプターからのフィードバックに対処された今、私たちはこれを安定版として認定する準備ができています。

「安定版」とは正確には何のことでしょうか?

以前にも混乱を招いた点なので、このセクションでこのリリースがNext.jsコミュニティにもたらすものを明確にします。

このリリースは特にnext dev --turboコマンドを安定版としてマークします。本番ビルド(next build --turbo)はまだサポートされていませんが、現在進行中ですので、続報をお待ちください。将来的にはNext.jsとは独立したTurbopackのスタンドアロンバージョンをリリースする予定ですが、まずはNext.jsコミュニティの体験を向上させることでその価値を証明したいと考えています。

次のセクションで説明する未サポート機能を除けば、TurbopackはNext.jsのすべての安定機能で動作するはずです。明確にするために、TurbopackはApp RouterとPages Routerの両方をサポートしています。実験的な機能はTurbopackで動作する場合としない場合がありますが、安定版とマークされるまでには確実に動作するようになります。

アプリケーションがwebpackのカスタマイズを行っているが、webpackローダーを追加しているだけであれば、Turbopack用にローダーを設定することで、すでにTurbopackを使用できる可能性があります。Turbopackでのwebpackローダーのサポートについては、ドキュメントを参照してください。

Turbopackで動作が確認されているwebpackローダーのリストです

  • @svgr/webpack
  • babel-loader
  • url-loader
  • file-loader
  • raw-loader
  • tsconfig-paths-webpack-plugin — そのままサポートされており、プラグインは不要です。
  • webpackローダーAPIの一部をサポートしているため、他のほとんどのローダーも動作します。

ほとんどのCSSおよびCSS-in-JSライブラリがサポートされています

  • サポート済み
    • Tailwind CSS
    • @emotion/react
    • Sass
    • styled-components
    • Bootstrap
    • Antd
    • node-sass
    • JSS
    • Emotion
    • theme-ui (Emotionを使用)
    • @chakra-ui/core (Emotionを使用)
    • aphrodite
  • 現在非対応
    • Less — less-loaderを追加できます。webpackを使用するNext.jsも、Lessをそのままではサポートしていません。
    • @vanilla-extract/css — カスタムwebpackプラグインを使用 — 将来的に必要なフックをサポートするために何が必要か検討する予定です。
    • StyleX — Babelトランスフォームとdata:属性のサポートが必要 — next build --turboが安定版になった後、StyleXのサポートを検討する予定です。

パフォーマンス

本日リリースされたバージョンのパフォーマンスはwebpackよりも格段に優れていることを強調したいのですが、これが最終的なパフォーマンス値ではありません。私たちはケント・ベックの有名な「まずは動かす。次に良くする。そして速くする」という公式に従ってきました。Next.jsとwebpackが10年近く成熟してきた範囲に追いつく必要があるため、これまでの努力の大部分は「まずは動かす」段階に費やされてきました。

Turbopackは、そのキャッシュインフラストラクチャに大きく賭けていますが、ご存知の通り、キャッシュはソフトウェア開発における唯一の2つの難しいことの1つです。経験から、キャッシュを明示的にそれ向けに構築されていないアーキテクチャに追加すると、望ましくない結果につながる可能性があることを知っていました。そのため、最もきめ細かい関数にもキャッシュを有効にしました。これは、コールドビルドとメモリ使用量を犠牲にして、リビルドが非常に高速になることを意味し、より良いバランスを目指して取り組んでいます。素晴らしい点は、以前の投稿で述べた高度なトレースを使用して、非効率性を見つけ、どの関数をキャッシュするのが最も価値があるかをプロファイルできることです。

過去3か月で、すでにいくつかの重要な改善を行いました。Next.js 15 RC 2のTurbopackと15 RC 1のTurbopackを比較すると、これらの最適化の結果が示されています。

  • メモリ使用量が平均で25〜35%削減されました。
  • 数千のモジュールを持つ大規模なページにおける初期コンパイルが30〜50%高速化されました。

Turbopackの安定版にはインメモリキャッシュが含まれており、開発サーバーを再起動するたびに再構築する必要があります。これは大規模なアプリケーションでは10秒以上かかることがあります。私たちが非常に期待しているのは、ディスク上の永続キャッシュをテストする際に得られている大きな成果であり、これについてはこの投稿の後半で説明します。

破壊的変更

独自のバンドラーを構築する大きな動機は、webpackの既存の動作に可能な限り合わせる必要性でした。これは、当時既存のどのソリューションでも保証できなかったことです。これには、ファイルの解決方法や、一部のnpmパッケージが使用するwebpackIgnoreコメントのようなwebpackの小さな機能が含まれます。

残念ながら、Turbopackおよび関連するNext.jsの実装を将来にわたって対応させるために、いくつかの機能を削除しなければなりませんでした。これらの機能は、webpackを使用する場合には引き続きサポートされます。

いくつかの注目すべき点があります。それらを変更せざるを得なかった理由を掘り下げてみましょう。

webpack()設定はサポートされていません。 Turbopackはwebpackではないため、同じ設定オプション構造を持っていませんが、多くの同じ機能をサポートしています。具体的には、webpackローダー解決エイリアスのサポートを実装しました。コードを変換するほとんどのwebpackローダーはすぐにサポートされます。webpackの子コンパイラやファイルの出力など、特殊なことを行う一部のwebpackローダーはサポートされていません。

.babelrcは自動的にコードを変換しません。 TurbopackはデフォルトでSWCを利用します。必要に応じてbabel-loaderを追加することはできますが、デフォルトが常に高速であり、アーキテクチャの観点からも理にかなっていることを保証しています。.babelrcを設定した場合でも、他の最適化を処理するためには常にSWCを実行する必要があります。これは、webpackがさらに最適化を行うために常にacornパーサーを実行しなければならないのと同様です。TurbopackでBabelの代わりにSWCを使用すると、一度だけ解析し、Turbopack全体で同じ抽象構文木(AST)をエンドツーエンドで活用できます。

あまり使用されないCSS Modulesの機能。 CSSの処理をPostCSSからLightning CSSに切り替えました。Lightning CSSは、CSS変換、ミニファイ、CSS Modulesをすぐにサポートする、非常に高速なCSSコンパイラです。その代わり、あまり使用されない一部の機能はサポートされていません。具体的には、:global:localの擬似セレクタ(関数形式の:global():local()は引き続き動作します)、@value、および:import / :export ICSSルールです。また、他のCSSパーサーよりも厳格で、エラーを無視するのではなく、コード内のエラーを指摘します。

Lightning CSSの追加過程で、私たちはプロジェクトに貢献しました。例えば、CSS Modulesの粒度の高いオプションを実装し、CSSグリッドのプレフィックスを無効にし、CSS Modulesのpureモードを実装しました。これにより、webpackのcss-loaderから移行する際に、CSS ModulesでLightning CSSを導入しやすくなります。また、サポートされていないCSS Modules機能のエラーも改善しました。

Lightning CSSの作者でありメンテナーであるDevon Govett氏の、このプロジェクトにおける継続的な協力に感謝いたします。

実験的な機能。 私たちはNext.jsにおけるTurbopackの安定性に注力しているため、まずNext.jsで利用可能な安定した機能に焦点を当てることにしました。

完全なリストについては、ドキュメントページをご覧ください。

ロードマップ

Turbopackは大きく進歩しましたが、まだ多くの作業が残っています。次に予定されている2つの注目すべき機能は、永続キャッシュとプロダクションビルドです。展開は以下の順序になる予定です。

  • 永続キャッシュ — 将来のマイナーリリース
  • ビルドベータ — 将来のマイナーリリース
  • ビルドリリース候補 — 将来のマイナーリリース
  • ビルド安定版 — 将来のマイナーリリース
  • 新規アプリケーションのcreate-next-appで推奨 — 将来のマイナーリリース
  • カスタムwebpack設定がない場合のNext.jsのデフォルト — 将来のメジャーリリース

webpackはNext.jsに残り続けますが、Turbopackの利点により、ほとんどのNext.jsアプリケーションがそれを使用することを望むと予想しています。プロダクションビルド用のTurbopackが完成したら、一般的に使用されるwebpackプラグインのサポートを開始する予定です。

Turbopackにはその先の漠然とした計画もありますが、この投稿では近い将来確実にリリースできるものに限定したいと思います。たった2つの機能について話しているだけかもしれませんが、それらには多くの要素が関わっているため、掘り下げる価値はあります。

永続キャッシュ(再起動をまたぐ高速リフレッシュ)

永続キャッシュとは、開発サーバーの再起動時や複数のプロダクションビルド間でコンパイラによる作業を再利用できるように、その作業を保存することを意味します。

要するに、Turbopackは再起動しても同じ作業をやり直すことを避けます。

「より速い高速リフレッシュ」セクションで述べたように、私たちは作業を並列化してキャッシュできるようにTurbo Engineを構築しました。これにより、ファイルを変更するたびに、そのファイル変更に関連する作業だけを実行すればよくなります。もし再起動後やルートを開いた際にもこの体験を提供できたらどうでしょう?以前の開発セッションで既に完了したコンパイル作業をやり直す必要がなくなります。以前の開発セッションでコンパイルされたルートやnext buildを使用した複数回のビルドでも、Fast Refreshの恩恵を受けられたらどうでしょう?

それがまさに私たちが取り組んできたことです。Turbo Engine用の新しいストレージ層で、コンパイル作業をディスクに永続化し、開発サーバーを起動したり再度ビルドしたりする際にそれを復元できるようにサポートします。

webpackにはNext.jsでデフォルトでディスクキャッシュが有効になっていますが、かなりの制限があります。キャッシュの大部分が機能するためにディスクから復元され、メモリに読み込まれる必要があることは注目に値します。十分にきめ細かいキャッシュがあるとは感じられませんでした。例えば、Vercelのより大規模なアプリケーションでは、キャッシュが十分に大きくなった場合、webpackのディスクキャッシュは最初からすべての作業を行うよりも遅くなることさえありました。

webpackの既存のディスクキャッシュとは異なり、Turbopackの永続キャッシュは再起動をまたぐ高速リフレッシュのように感じられます。初回コンパイルに10秒以上かかったルートでも、一度コンパイルされてしまえば、キャッシュからの復元は500ms未満で完了します。

Turbopackを使用したnext buildでも同様の結果が見られ、変更されたファイルのみが再コンパイルされ、それ以外はそのままです。next buildが実行する複数のステップの中で、これにより時間の大部分がコンパイルとバンドルからTypeScriptの型チェックの実行に移ります。

永続キャッシュは現在開発中であり、まず社内のNext.jsアプリケーションを使用して検証したいと考えています。初期の結果は非常に有望であり、これらのホットパスを最適化し続けることで、時間の経過とともにパフォーマンスはさらに向上するでしょう。

永続キャッシュが安定すれば、デフォルトで有効になります。永続キャッシュを有効にするためにコードベースの変更は必要ありません。

永続キャッシュのテストにご興味があれば、ぜひお問い合わせください!

プロダクションビルド

Turbopackでの安定したプロダクションビルドに向けて、大きな進捗を遂げていることをお伝えできることを嬉しく思います。現在、プロダクションテストの96%がパスしており、これは大きな前進です。しかし、大規模なプロダクション環境でTurbopackを自信を持って推奨できるようになるまでには、まだ多くの作業が必要な領域があります。

プロダクションビルドは、開発と比較して独自の課題を伴い、私たちはそれらに対処するために積極的に取り組んでいます。以下では、すでに最適化された点と、現在進行中の点について説明します。

プロダクション最適化

正確性

正確性の確保は、信頼性の高いプロダクションビルドに不可欠です。現在の状況は以下の通りです

  • CSSチャンキング: 進行中。この機能は、CSSを小さなチャンクに分割し、アプリケーションの各部分に必要なCSSのみを読み込むことを可能にするため、ロード時間の短縮とCSSルールの正しい順序付けを保証する上で重要です。
  • プロダクションJSランタイム: 完了。これにより、JavaScriptランタイムがプロダクション環境で期待通りに動作し、信頼性と安定性を提供することが保証されます。
  • コンテンツベースのファイル名ハッシュ化: 未実装。コンテンツベースのハッシュ化により、コンテンツに基づいてファイル名を生成できるようになり、ブラウザでのより効率的な長期キャッシュが可能になります。

UXパフォーマンス最適化

UXパフォーマンスは、高速なロード時間と効率的なリソース使用を実現する上で重要です。以下に、私たちが取り組んでいることを示します。

  • JSミニファイ: 完了。Next.js 13以降、Next.jsがwebpackと連携してすでに使用しているSWC Minifyを実装しました。
  • CSSミニファイ: 完了。Lightning CSSによるCSSミニファイを実装しました。これはスタイルシートのサイズ削減に重要です。
  • グローバル情報(アプリケーション全体の最適化): 完了。Turbopackは、アプリケーション内のすべてのルートに関するデータを必要とする最適化(例: モジュールIDハッシュ化)を適用できます。
  • ツリーシェイキング: 部分的に完了。現在進行中。未使用コードの削除とバンドルサイズの削減に役立つツリーシェイキングを部分的にサポートしています。しかし、まだツリーシェイキングが完全に機能しないシナリオがあります。
    • 動的インポート: next/dynamicを使用するような動的インポートでは、ツリーシェイキングに制限があります。
    • 複雑なエクスポート: export { foo as "string name" }のような特定のエクスポートタイプ。
    • 非ESモジュール: CommonJSモジュールはツリーシェイクできません。
    • バレルファイル: バレルファイルからの再エクスポートは非効率であり、副作用のないモジュールのスキップに制限があります。
    • 断片化: 場合によっては、ツリーシェイキングが多すぎる断片を作成し、非効率なバンドルにつながることがあります。
  • モジュールIDハッシュ化(部分): 進行中。モジュールIDハッシュ化は部分的に実装されていますが、パフォーマンス向上に取り組んでいます。完全に有効になると、最終バンドルサイズの削減に役立ちます。
  • エクスポート名マングリング: 進行中。これは、最終バンドルサイズを削減するために、エクスポート名のサイズを縮小することを含みます。
  • スコープホイスティング: 未実装。スコープホイスティングは、小さなJavaScriptモジュールを単一のスコープにマージすることでバンドルサイズを削減し、オーバーヘッドを減らしてパフォーマンスを向上させるのに役立ちます。
  • プロダクション最適化JSチャンキング: 未実装。JavaScriptの重複を最小限に抑えるためのチャンキングは、特に大規模なアプリケーションにおいて、ロードパフォーマンスを向上させるために不可欠です。

今後の情報にご期待ください

next dev --turboを自信を持って推奨できることを大変嬉しく思います。皆様の開発体験がどのように向上するかをお聞きするのが待ちきれません。ぜひ今日お試しになり、ご自身でパフォーマンスの向上をご確認ください。

これはほんの始まりに過ぎません。永続キャッシュとプロダクションビルドが間近に迫っており、これらはワークフローにさらなる速度と信頼性をもたらすでしょう。

正確性を確保し、最大のアプリケーションでもシームレスに処理できるようパフォーマンスを最適化するにつれて、さらなるアップデートを共有していきます。Turbopackを開発ビルドとプロダクションビルドの両方にとって最高のソリューションにするために取り組んでいますので、今後のリリースと改善にご期待ください。

貢献者

Turbopackのベータ版およびリリース候補版の段階を通じて、テストに参加し、問題を報告し、修正を検証してくださった数千人の開発者の皆様に感謝いたします。

このリリースは以下のチームによって提供されました