ナビゲーション リクエストの処理

サービス ワーカーを使用して、ネットワークを待たずにナビゲーション リクエストに応答します。

ナビゲーション リクエストは、ナビゲーション バーに新しい URL を入力したときや、ページ上のリンクをクリックして新しい URL に移動したときに、ブラウザが HTML ドキュメントに対して行うリクエストです。これが、サービス ワーカーがパフォーマンスに最も大きな影響を与える部分です。サービス ワーカーを使用してネットワークを待たずにナビゲーション リクエストに応答すると、ネットワークが利用できない場合でも、ナビゲーションが確実に高速化され、復元力も高まります。これは、HTTP キャッシュで可能なことと比較して、サービス ワーカーがもたらすパフォーマンス上の最大のメリットです。

ネットワークから読み込まれたリソースを特定するガイドで詳しく説明されているように、ナビゲーション リクエストは、ネットワーク トラフィックの「ウォーターフォール」で実行される多数のリクエストのうちの最初のリクエストです。ナビゲーション リクエストで読み込まれた HTML は、画像、スクリプト、スタイルなどのサブリソースに対する他のすべてのリクエストのフローを開始します。

サービス ワーカーの fetch イベント ハンドラ内で、FetchEventrequest.mode プロパティをチェックすることで、リクエストがナビゲーションかどうかを判断できます。'navigate' に設定されている場合は、ナビゲーション リクエストです。

一般的なルールとして、長時間存続する Cache-Control headers を使用して、ナビゲーション リクエストの HTML レスポンスをキャッシュに保存しないでください。通常は、Cache-Control: no-cache を使用してネットワーク経由で満たす必要があります。これにより、HTML と後続のネットワーク リクエストのチェーンが(合理的に)最新の状態になります。ユーザーが新しいページに移動するたびにネットワークにアクセスすると、各ナビゲーションが遅くなる可能性があります。少なくとも、高速で信頼性に優れたものにはなりません。

アーキテクチャのさまざまなアプローチ

ネットワークを使用せずにナビゲーション リクエストに応答する方法を把握するのは難しい場合があります。適切なアプローチは、ウェブサイトのアーキテクチャと、ユーザーが移動する可能性のある一意の URL の数に大きく依存します。

万能なソリューションはありませんが、以下の一般的なガイドラインは、最も有効なアプローチを判断する際に役立ちます。

小規模な静的サイト

ウェブアプリが比較的少数(数十程度)の一意の URL で構成され、各 URL が異なる静的 HTML ファイルに対応している場合は、これらの 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 を実装できる場合があります。これは、サーバー環境とサービス ワーカー環境の間でルーティング情報とテンプレート情報を共有できる場合に最適です。特に、ウェブサーバーが JavaScript を使用している場合(ファイル システム アクセスなどの Node.js 固有の機能に依存していない場合)に適しています。

ご利用のウェブサーバーがこのカテゴリに該当し、HTML 生成をネットワークからサービス ワーカーに移行する方法について検討したい場合は、Beyond SPAs: 代替のアーキテクチャ for your PWA のガイダンスを参照してください。

その他

キャッシュに保存された HTML でナビゲーション リクエストに応答できない場合は、(HTML 以外の他のリクエストを処理するために)サイトにサービス ワーカーを追加しても、ナビゲーションの速度が低下しないようにする必要があります。ナビゲーション リクエストに応答するために使用せずにサービス ワーカーを起動すると、少量のレイテンシが発生します(サービス ワーカーを使用して高速で復元力の高いアプリを作成するで説明しています)。このオーバーヘッドを軽減するには、ナビゲーションのプリロードという機能を有効にして、fetch イベント ハンドラ内にプリロードされたネットワーク レスポンスを使用するとよいでしょう。

Workbox には、ナビゲーションのプリロードがサポートされているかどうかを機能検出するヘルパー ライブラリが用意されています。サポートされている場合は、ネットワーク レスポンスを使用するようにサービス ワーカーに指示するプロセスが簡素化されます。

写真撮影: Aaron BurdenUnsplash