サービス ワーカーを使用して、ネットワークを待たずにナビゲーション リクエストに応答する。
ナビゲーション リクエストとは、ナビゲーション バーに新しい URL を入力したり、ページ上のリンクをたどって新しい URL に移動したりするたびに、ブラウザによって行われる HTML ドキュメントのリクエストです。ここで、Service Worker がパフォーマンスに最も大きな影響を与えます。Service Worker を使用して、ネットワークを待たずにナビゲーション リクエストに応答すると、ネットワークが利用できない場合でも、ナビゲーションを確実に高速化できます。これは、HTTP キャッシュで可能なことと比較して、Service Worker から得られる最大のパフォーマンス上のメリットです。
ネットワークから読み込まれたリソースを特定するガイドで詳しく説明されているように、ナビゲーション リクエストは、ネットワーク トラフィックの「ウォーターフォール」で行われる可能性のある多くのリクエストの最初のものです。ナビゲーション リクエストを介して読み込まれる HTML は、画像、スクリプト、スタイルなどのサブリソースに対する他のすべてのリクエストのフローを開始します。
Service Worker の fetch イベント ハンドラ内で、FetchEvent の request.mode プロパティをチェックすることで、リクエストがナビゲーションかどうかを判断できます。'navigate' に設定されている場合は、ナビゲーション リクエストです。
原則として、ナビゲーション リクエストの HTML レスポンスをキャッシュに保存するために、有効期間の長い Cache-Control headers を使用しないでください。通常、HTML とそれに続く一連のネットワーク リクエストが(合理的に)最新であることを確認するために、Cache-Control: no-cache を使用してネットワーク経由で満たす必要があります。ユーザーが新しいページに移動するたびにネットワークにアクセスすると、残念ながら、移動のたびに時間がかかる可能性があります。少なくとも、安定して高速になることはありません。
アーキテクチャのさまざまなアプローチ
ネットワークを回避しながらナビゲーション リクエストにどのように対応するかを判断するのは、難しい場合があります。どちらのアプローチが適しているかは、ウェブサイトのアーキテクチャと、ユーザーがアクセスする可能性のある一意の URL の数によって大きく異なります。
万能なソリューションはありませんが、次の一般的なガイドラインは、どのアプローチが最も有効かを判断するのに役立ちます。
小規模な静的サイト
ウェブアプリが比較的少数の(数十個程度の)一意の URL で構成され、それらの URL がそれぞれ異なる静的 HTML ファイルに対応している場合、実行可能なアプローチの 1 つは、それらの HTML ファイルをすべてキャッシュに保存し、適切なキャッシュに保存された HTML でナビゲーション リクエストに応答することです。
事前キャッシュを使用すると、サービス ワーカーがインストールされるとすぐに HTML を事前にキャッシュに保存し、サイトを再ビルドしてサービス ワーカーを再デプロイするたびに、キャッシュに保存された HTML を更新できます。
また、ユーザーがサイトの一部の URL にのみ移動する傾向があるなどの理由で、すべての HTML をプリキャッシュしないようにする場合は、stale-while-revalidate ランタイム キャッシュ戦略を使用できます。ただし、この方法では、個々の HTML ドキュメントが個別にキャッシュされ、更新されるため、注意が必要です。HTML にランタイム キャッシュを使用するのが最も適しているのは、同じユーザーが頻繁に再アクセスする URL が少数で、それらの URL が互いに独立して再検証されることに問題がない場合です。
シングルページ アプリ
シングルページ アーキテクチャは、最新のウェブ アプリケーションでよく使用されます。この場合、クライアントサイドの JavaScript がユーザーのアクションに応じて HTML を変更します。このモデルでは、History API を使用して、ユーザーがウェブアプリを操作するときに現在の URL を変更します。これにより、実質的に「シミュレートされた」ナビゲーションが実現します。後続のナビゲーションは「偽」である可能性がありますが、最初のナビゲーションは本物であり、ネットワーク上でブロックされないようにすることが重要です。
幸いなことに、シングルページ アーキテクチャを使用している場合は、キャッシュから最初のナビゲーションを提供するために従うべき簡単なパターンがあります。それがアプリケーション シェルです。このモデルでは、リクエストされた URL に関係なく、サービス ワーカーは、すでに事前キャッシュされている同じ単一の HTML ファイルを返すことで、ナビゲーション リクエストに応答します。この HTML は、一般的な読み込みインジケーターやスケルトン コンテンツなどで構成される、必要最小限のものにする必要があります。ブラウザがキャッシュからこの HTML を読み込むと、既存のクライアントサイド JavaScript が引き継ぎ、元のナビゲーション リクエストから URL の正しい HTML コンテンツをレンダリングします。
Workbox には、このアプローチを実装するために必要なツールが用意されています。navigateFallback
option を使用すると、アプリケーション シェルとして使用する HTML ドキュメントを指定できます。また、オプションの許可リストと拒否リストを使用して、この行動を URL のサブセットに制限することもできます。
マルチページ アプリ
ウェブサーバーがサイトの HTML を動的に生成する場合や、数十を超える一意のページがある場合は、ナビゲーション リクエストを処理する際にネットワークを回避することははるかに困難です。その他のアドバイスが適用される可能性があります。
ただし、マルチページ アプリの特定のサブセットでは、ウェブサーバーで使用されるロジックを完全に複製して HTML を生成する Service Worker を実装できる場合があります。この方法は、サーバー環境と Service Worker 環境の間でルーティング情報とテンプレート情報を共有できる場合、特にウェブサーバーが JavaScript を使用している場合(ファイル システム アクセスなどの Node.js 固有の機能に依存しない場合)に最適です。
ウェブサーバーがこのカテゴリに該当し、HTML 生成をネットワークからサービス ワーカーに移行する方法を検討する場合は、SPA の先へ: PWA の代替アーキテクチャのガイダンスをご覧ください。
その他
キャッシュに保存された HTML でナビゲーション リクエストに応答できない場合は、サイトに Service Worker を追加して(HTML 以外のリクエストを処理する)、ナビゲーションの速度が低下しないようにする必要があります。ナビゲーション リクエストへの応答に使用せずに Service Worker を起動すると、わずかなレイテンシが発生します(Service Worker を使用した、より高速で復元性の高いアプリの構築を参照)。このオーバーヘッドを軽減するには、ナビゲーション プリロードと呼ばれる機能を有効にして、fetch イベント ハンドラ内でプリロードされたネットワーク レスポンスを使用します。
Workbox には、ナビゲーション プリロードがサポートされているかどうかを機能検出するヘルパー ライブラリが用意されています。サポートされている場合は、ネットワーク レスポンスを使用するように Service Worker に指示するプロセスが簡素化されます。