Parcel v2.8.0

Parcel v2.8.0 のリリースを発表できることを嬉しく思います!このリリースには、改良された自動コード分割を備えたまったく新しいバンドルアルゴリズム、大規模プロジェクトのビルドパフォーマンスの大幅な向上、および多くのバグ修正が含まれています。また、HMR更新のパフォーマンスの大幅な向上と、バンドルサイズを最大50%削減したツリーシェイキングの変更も含まれています。

新しいバンドルアルゴリズム

#

最初のv2リリース以来、Parcelは自動コード分割をサポートしており、アプリの複数の部分(例:ページ、動的インポートなど)間で共有モジュールを重複排除します。これにより、Reactやデザインシステムなどの一般的に使用される依存関係をアプリケーションコードから独立してキャッシュでき、ページ間を移動する際にロードする必要があるコードの量を削減できます。自動化されているため、開発者が手動で設定または更新する必要がなく、変更を加えてもアプリを最適な状態に保ちます。

初期の実装は、小規模から中規模のプロジェクトではうまく機能しましたが、大規模プロジェクトではスケーラビリティの問題が発生しました。アルゴリズムには多くのネストされたグラフ走査(2乗の時間計算量)が含まれており、後で元に戻される作業を行うことがよくありました。さらに、実装にバグがあり、不要な重複が発生したり、モジュールが欠落したりすることがありました。

Atlassianのチームが、これらの問題を解決する新しいバンドルアルゴリズムを提供しました。これにより、ビルド時間と実行時パフォーマンスが大幅に向上します。これは、以前の実装とは異なるアプローチを取ります。手動のコード分割ポイント(例:動的インポート)に基づいてすべての資産を最初にバンドルに配置し、後で重複を削除するのではなく、重複のないグラフ(各資産は1つのバンドルにのみ存在する)から開始します。その後、並列リクエスト制限や最小バンドルサイズ要件などの制約を満たすために必要に応じてバンドルを結合します。また、より多くの情報を事前に計算し、ネストされたグラフ走査を削除することで、時間計算量も削減します。

これにより、バンドルサイズが小さくなり、ビルド速度が大幅に向上します。6万を超える資産を持つ非常に大規模な現実世界のプロジェクトでは、全体のビルド時間が25分以上から9分に短縮されました(**2.7倍高速化**)。プロジェクト全体の総バンドルサイズは、952 MBから370 MBに減少しました(**2.5倍縮小**)。比較として、Webpackを使用して同じアプリをビルドするには45分以上かかります。

この新しいバンドルアルゴリズムの開発には長い時間を費やしてきましたが、このリリースでついにデフォルトにすることができ、大変嬉しく思っています。この改善に貢献してくれたAtlassianチームに感謝します!

HMR再構築パフォーマンス

#

バンドルパフォーマンスの向上に加えて、増分再構築とHMR更新をさらに高速化するための作業も行ってきました。このリリースには、増分バンドル、シングルスレッドコンパイル、早期HMR更新という3つの新しい機能が含まれています。

一部のツールは、ブラウザでESMを利用して各モジュールを個別にロードすることにより、開発中にバンドルを完全に回避します。つまり、ファイルが変更された場合、全体のバンドルを再計算するのではなく、そのファイルのみを変換する必要があります。ただし、モジュールが多い大規模プロジェクトでは、このアプローチにより、ブラウザはページロード時に数百または数千ものカスケードHTTPリクエストを行う必要があります。さらに、HMR更新を実行する場合、ブラウザは更新された各ファイルを再ロードするためのネットワークリクエストを行う必要があります。ESMモジュールレジストリでモジュールを無効にする方法がないため、依存モジュールも手動で更新する必要があります。

Parcelには、本番環境のものよりもはるかに少ない作業を行う開発専用のパッケージャーが既にありますが(例:ツリーシェイキングなし)、大規模アプリの場合、上記のバンドルアルゴリズムはまだボトルネックになる可能性があります。ただし、ほとんどのコード変更は非常にシンプルであり、依存関係の追加または削除を行わずに、単一のファイルのみに影響します。これらの場合、再バンドルは不要であり、Parcelは全体のバンドルアルゴリズムを再実行せずに、資産をその場で更新できます。さらに、Parcelは、単一のファイルのみが変更された場合、メインスレッドでコンパイルとパッケージングを行い、ワーカー間でバンドルグラフをシリアル化するコストを回避します。

この増分バンドルは大きな違いをもたらします。たとえば、上記の大規模プロジェクトの再構築時間は、40秒から4秒に短縮されました(**10倍高速化**)!

さらに、Parcelはバンドルのパッケージングが完了する前に、WebSocket経由でブラウザにHMR更新を送信するようになりました。開発専用の独自モジュール形式により、変更されたモジュールを再評価し、追加のネットワークリクエストなしでその場で交換できます。これは事実上、HMR更新にはバンドルされていない場合と同じ量の作業が必要であることを意味し、プロジェクトのサイズではなく変更のサイズに合わせてスケーリングされ、ページロード中にネットワークウォーターフォールを回避します。

他のツールと比較して、エンドツーエンドのHMR更新パフォーマンスのベンチマークテストを実施しました。次の結果は、1000個のコンポーネントを持つReactアプリで、ファイルを保存してからブラウザで更新が表示されるまでの時間を示しています。

Vite Turbopack Parcel
ルート 293.5ms 274.8ms 88.6ms
リーフ 143.8ms 57ms 37.4ms

完全なベンチマークソースコードと結果については、このリポジトリを参照してください。

ツリーシェイキングの改善

#

このリリースには、コード分割によるツリーシェイキングの改善も含まれています。以前は、多くの再エクスポートを含むインデックスファイルを含む大規模なライブラリを使用した場合、Parcelは常に使用されているエクスポートをすべて同じバンドルに配置していました。たとえば、異なるページまたはコード分割ポイント(例:動的インポート)でコンポーネントライブラリの異なるコンポーネントを使用した場合、プロジェクト全体のすべての使用済みコンポーネントがエントリバンドルに配置されます。これは、最初のページロード時に必要なJavaScriptよりもはるかに多くのJavaScriptをロードすることを意味する可能性があります。

Parcelは、途中で検出されたすべての再エクスポートに従って、最終的な宛先にポインターを書き換えます。これは、副作用のないパッケージの再エクスポートはコード分割に影響を与えなくなり、各バンドル内の使用されているエクスポートのみがロードされることを意味します。多くのアプリケーションでは、必要なときにのみコードがロードされるため、エントリバンドルが小さくなります。

結果は、依存する再エクスポートの数とコード分割の設定によって異なりますが、いくつかのアプリケーションで印象的な改善が見られました。非常に大規模なアプリでは、**JSエントリバンドルが40%以上縮小**され、別のアプリではJSエントリが25%、CSSが50%縮小されました。

この改善に貢献してくれたNiklas Mischkulnigに感謝します!

感謝!

#

Parcel v2.8.0には、その他にもいくつかの小さな機能、バグ修正、および改善が含まれています。詳細については、完全なリリースノートをご覧ください。