Lazy Route Discovery(Fog of War)からReact Router v7のルーティングについて理解する
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjOATYckFaQ-PTdTnFmZ-w-HCfP9QBhiOPXAa7fswzjrK8lVwUqDCqX7wdP0Y89IPLR3GJF6PZzmIgrLflbaghoawNp9CXbmTOpTSDVmvOQKB0uZm9pg773zEJNHWQO58wdLICDcpMfeE/s800/vacation_drive.png
(React Router v7をReactのフレームワークとして利用することを前提としています。)
【前提】
Linkやredirectを利用してページ遷移する際に/__mamifestへのリクエストが実行されます。(ChromeのDevToolsなどで確認できます)
このAPIについて調査していると、Remix v2で公開されたLazy Route Discovery(Fog of War)に関係していることが分かりました。
そこで今回は、公式ブログの「Fog of War」を参考にReact Router v7のルーティングについて理解したことをまとめます。
【Lazy Route Discovery】
Lazy Route Discovery(以下、Fog of War)はReact Routerによる、コンテンツ描画の最適化のための仕組みです。React Routerでは「ルートの探索」と「対象ページに必要なデータへのprefetch」を並行実行することでネットワーク上のウォーターフォールを避けることを目的としています。React RouterではRoute Manifestと呼ばれるマニフェストを参照してprefetchを実行しますが、このRoute Manifestを逐次パッチしていくことがLazy Route Discoveryの実態です。
【Route Manifest】
Route Manifestとは、マッチしたURLとメタ情報を管理しているマニフェストです。jsonで表現されており、prefetchするデータの対象の有無(loaderの有無、actionの有無)を管理しています。Route Manifestは各ルート事に管理されており、testページへの遷移時には/manifest?p=testへのリクエストが実行されることで、下記のようなRoute Manifestを取得します。
code:test.json
{
"root": {
"id": "root"
"path": ""
"hasClientAction": false,
"hasLoader": true,
"hasClientLoader": true,
"hasErrorBoundary": true,
"routes/test": {
"id": "routes/test",
"parentId": "root",
"path": "test",
"hasClientAction": false,
"hasLoader": true,
"hasClientLoader": true,
"hasErrorBoundary": false,
...
}
...
}
}
このRouteマニフェストを利用することで、prefetchに必要なデータの参照を可能にします。
【Lazy Route Discovery(Fog of War)はなぜ必要なのか】
Fog of Warの実装前は、Route Manifestがすべてのルート分用意されていました。つまり、マニフェスト数はアプリケーションの規模に比例するため、大規模なアプリケーションの場合は、マニフェストが肥大化していくため、モジュールのロード等に影響を与え、結果としてページの読み込み速度が低下する可能性がありました。そこで、Fog of WarではミニマムなRoute Manifestのみを生成し、レンダリングされたページ内の<Link prefetch>を認識するたびにマニフェストにパッチを当てます(Eager Route Discovery)。こうすることで、Route Manifestを動的に増加させていくことが可能となり、ページの読み込み速度の低下を防ぎます。
【余談】
マニフェストのパッチ中に、リンクをクリックした場合はprefetchが完了していない場合があるので、遷移中にfetchが走り、ブラウザのブルリロードが走る可能性があります。一度アクセスしたルートでEager Route Discoveryが実行されることはないです。つまり、React Router v7でリンクを配置する際には可能な限り<Link prefetch>を利用することが期待されるでしょう。