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

Service Worker を使用して、ネットワークで待機することなくナビゲーション リクエストに応答する。

ナビゲーション リクエストとは、ナビゲーション バーに新しい URL を入力するか、新しい URL に移動するページ上のリンクをクリックするたびに、ブラウザによって作成される HTML ドキュメントに対するリクエストです。ここで、Service Worker がパフォーマンスに最も大きく影響します。ネットワークを待たずに Service Worker を使用してナビゲーション リクエストに応答すると、ネットワークが利用できないときの復元性に加え、ナビゲーションを確実に高速にすることができます。これは、HTTP キャッシュで可能なことに対して、Service Worker が実現するパフォーマンスの面で最大のメリットです。

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

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

原則として、有効期間の長い Cache-Control headers を使用してナビゲーション リクエストの HTML レスポンスをキャッシュに保存しないでください。通常、これらはネットワークを介して Cache-Control: no-cache で満たされ、HTML と後続のネットワーク リクエストのチェーンが(合理的な)新鮮な状態になるようにします。ユーザーが新しいページに移動するたびに、ネットワークにアクセスしなければ、各ナビゲーションが遅くなる可能性があります。少なくとも、確実に高速になることはありません。

アーキテクチャに対するさまざまなアプローチ

ネットワークを回避しながらナビゲーションのリクエストにどう対応するかの方法を把握するのは簡単ではありません。適切なアプローチは、ウェブサイトのアーキテクチャと、ユーザーが移動する可能性のある一意の URL の数に大きく依存します。

すべてのソリューションに当てはまる万能なソリューションはありませんが、次の一般的なガイドラインを参考にして、最適なアプローチを判断してください。

小規模の静的サイト

ウェブアプリが比較的少数の一意の URL(数十など)で構成され、各 URL が異なる静的 HTML ファイルに対応している場合、有効な方法の一つは、それらの HTML ファイルをすべてキャッシュに保存し、キャッシュされた適切な HTML でナビゲーション リクエストに応答することです。

プレキャッシュを使用すると、Service Worker のインストール後すぐに HTML を事前にキャッシュに保存できます。キャッシュした HTML は、サイトを再構築して Service Worker を再デプロイするたびに更新されます。

または、ユーザーがサイト上の一部の URL のみにアクセスする傾向があるなど、HTML をすべてプレキャッシュすることを避けたい場合は、stale-while-revalidate ランタイム キャッシュ戦略を使用できます。ただし、個々の HTML ドキュメントは個別にキャッシュおよび更新されるため、この方法には注意が必要です。HTML にランタイム キャッシュを使用するのは、同じユーザーセットによって頻繁に再アクセスされる URL の数が少なく、それらの URL が個別に再検証されることに不安を感じる場合に最適です。

シングルページ アプリ

シングルページ アーキテクチャは、最新のウェブ アプリケーションで頻繁に使用されます。このファイル内で、クライアント側の JavaScript はユーザーの操作に応じて HTML を変更します。このモデルでは、History API を使用して、ユーザーがウェブアプリを操作する際に現在の URL を変更し、実質的に「シミュレーション」されたナビゲーションを行います。その後のナビゲーションは「フェイク」かもしれませんが、最初のナビゲーションは実際のものです。ネットワーク上でブロックされないようにすることが重要です。

幸い、シングルページ アーキテクチャを使用している場合は、キャッシュから最初のナビゲーションを提供する簡単なパターンとして、アプリケーション シェルを使用できます。このモデルでは、リクエストされた URL に関係なく、Service Worker がナビゲーション リクエストに応答して、すでに事前にキャッシュされている単一の HTML ファイルを返します。この HTML は単純で、汎用の読み込みインジケーターやスケルトン コンテンツなどで構成されている必要があります。ブラウザがこの HTML をキャッシュから読み込むと、既存のクライアントサイドの JavaScript が処理を引き継ぎ、元のナビゲーション リクエストの URL に適した HTML コンテンツをレンダリングします。

Workbox には、この方法を実装するために必要なツールが用意されています。navigateFallback option を使用すると、App Shell として使用する HTML ドキュメントを指定できます。また、この動作を URL のサブセットに制限する許可リストと拒否リストも指定できます。

マルチページ アプリ

ウェブサーバーでサイトの HTML が動的に生成される場合や、一意のページが数十個以上ある場合は、ナビゲーション リクエストを処理する際にネットワークを回避することがはるかに困難になります。「その他のメール」のアドバイスが該当する可能性があります。

ただし、マルチページ アプリの一部では、ウェブサーバーで使用されているロジックを完全に複製して HTML を生成する Service Worker を実装できる場合があります。これは、サーバー環境と Service Worker 環境の間でルーティングとテンプレートの情報を共有できる場合、特にウェブサーバーが(ファイル システムへのアクセスなどの Node.js 固有の機能に依存せずに)JavaScript を使用する場合に最適です。

ウェブサーバーがこのカテゴリに該当し、HTML 生成をネットワークから Service Worker に移行する方法を検討したい場合は、SPA を超えて: PWA の代替アーキテクチャのガイダンスをご覧ください。

その他

キャッシュされた HTML でナビゲーション リクエストに応答できない場合は、(HTML 以外の他のリクエストを処理するために)Service Worker をサイトに追加することによってナビゲーションが遅くならないようにするための手順が必要です。ナビゲーション リクエストへの応答に Service Worker を使用せずに起動すると、わずかなレイテンシが発生します(Service Worker でより高速で復元性の高いアプリをビルドするを参照)。このオーバーヘッドを軽減するには、ナビゲーション プリロードという機能を有効にしてから、fetch イベント ハンドラ内でプリロードされているネットワーク レスポンスを使用します。

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

写真撮影: Aaron Burden、出典: Unsplash