オンラインに戻ったときにリクエストを再試行する

ウェブサーバーへのリクエストを行うと、エラーが発生する可能性があります。お客様の接続が切断されたか、リモート サーバーがダウンしている可能性があります。

このドキュメントでは、主に Service Worker での GET リクエストの処理に焦点を当ててきましたが、POSTPUTDELETE などの他のメソッドも使用できます。これらのメソッドは、バックエンド API と通信してウェブアプリにデータを提供する目的でよく使用されます。Service Worker が存在しない場合にこれらのリクエストが失敗した場合、オンラインに戻ったときにユーザーが手動で再試行する必要がありますが、これは常にユーザーが覚えておくべきことではありません。

これがアプリケーションの状況であり、Service Worker が複数存在する場合は、ユーザーがオンラインに戻ったときに失敗したリクエストの送信を再試行するのが理想的です。この問題の解決策として、BackgroundSync API があります。Service Worker は失敗したネットワーク リクエストを検出し、接続が返されたことをブラウザが検出したときに sync イベントを受け取るように登録できます。sync イベントは、ユーザーが登録したページから移動した場合でも配信できるため、失敗したリクエストを再試行する他の方法よりも効果的です。

Workbox は、workbox-background-sync モジュールでこの API を抽象化し、他の Workbox モジュールで BackgroundSync API を使用しやすくします。また、BackgroundSync にまだ対応していないブラウザ向けのフォールバック戦略も実装します。

基本的な使用方法

BackgroundSyncPluginworkbox-background-sync モジュールからエクスポートされ、失敗したリクエストをキューに入れて、将来の sync イベントが発生したときに再試行するために使用できます。

import {BackgroundSyncPlugin} from 'workbox-background-sync';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

const bgSyncPlugin = new BackgroundSyncPlugin('myQueueName', {
  maxRetentionTime: 24 * 60 // Retry for max of 24 Hours (specified in minutes)
});

registerRoute(
  /\/api\/.*\/*.json/,
  new NetworkOnly({
    plugins: [bgSyncPlugin]
  }),
  // An optional third parameter specifies the request method
  'POST'
);

ここで、BackgroundSyncPlugin は、JSON データを取得する API ルートへの POST リクエストに一致するルートに適用されます。ユーザーがオフラインの場合、BackgroundSyncPlugin はユーザーが再びオンラインになったときにリクエストを再試行しますが、その期間は最大 1 日です。

高度な使用方法

workbox-background-sync には、失敗したリクエストをインスタンス化して追加できる Queue クラスも用意されています。BackgroundSyncPlugin の場合と同様に、失敗したリクエストは IndexedDB に保存され、接続が復元されたとブラウザが判断したときに試行されます。

キューの作成

キューを作成するには、キュー名を表す文字列を使用して Queue オブジェクトをインスタンス化します。

import {Queue} from 'workbox-background-sync';

const queue = new Queue('myQueueName');

キュー名は、グローバル SyncManagerregister() メソッドで作成されるタグ名の一部として使用されます。また、IndexedDB データベースによって提供されるオブジェクト ストアに使用される名前でもあります。

リクエストをキューに追加する

Queue インスタンスを作成した後、pushRequest() メソッドを使用して、失敗したリクエストをインスタンスに追加できます。

import {Queue} from 'workbox-background-sync';

const queue = new Queue('myQueueName');

self.addEventListener('fetch', (event) => {
  // Add in your own criteria here to return early if this
  // isn't a request that should use background sync.
  if (event.request.method !== 'POST') {
    return;
  }

  const bgSyncLogic = async () => {
    try {
      const response = await fetch(event.request.clone());
      return response;
    } catch (error) {
      await queue.pushRequest({request: event.request});
      return error;
    }
  };

  event.respondWith(bgSyncLogic());
});

キューに追加されると、Service Worker が sync イベントを受け取ると、ブラウザはネットワークが再び使用可能になったと認識するため、リクエストが自動的に再試行されます。BackgroundSync API をサポートしていないブラウザは、Service Worker が起動するたびにリクエストを再試行します。失敗したリクエストを再試行する場合には効果的ではありませんが、一種のフォールバックです。

workbox-background-sync をテストしています

バックグラウンド同期の動作のテストには注意が必要ですが、Chrome DevTools でテストできます。現時点での最善のアプローチは次のようになります。

  1. Service Worker を登録するページを読み込みます。
  2. パソコンのネットワーク接続やウェブサーバーをオフにします。Chrome DevTools のオフライン切り替えボタンは使用しないでください。[オフライン] チェックボックスはページからのリクエストにのみ影響しますが、Service Worker のリクエストは引き続き処理されます。
  3. workbox-background-sync でキューに入れるべきネットワーク リクエストを作成します。キューに追加されたリクエストは、Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests で確認できます。
  4. ネットワーク接続を復元するか、ウェブサーバーをオンにします。
  5. Chrome DevTools > Application > Service Workers に移動して、早期の sync イベントを強制します。タグ名「workbox-background-sync:<your queue name>」を入力します。ここで、<your queue name> は設定したキューの名前です。
  6. [同期] をクリックします。ボタン。
    Chrome の DevTools のアプリケーション パネルにあるバックグラウンド同期ユーティリティのスクリーンショット。同期イベントが「myQueueName」キューに指定されています。「workbox-background-sync」には説明します。
  7. 以前に失敗したネットワーク リクエストが再試行され、正常に完了するはずです。その結果、リクエストが正常に再生されたため、IndexedDB ストアは空になります。

まとめ

workbox-background-sync を使用して失敗したネットワーク リクエストを再試行すると、API に送信しようとしているデータが失われないように、失敗した API リクエストをユーザーが再送信できるようにするなど、ユーザー エクスペリエンスとアプリの信頼性を向上させる優れた方法になる可能性があります。また、分析など、独自のデータに存在するギャップを埋めることもできます。実際、workbox-google-analytics モジュールは、Google アナリティクスへのデータ送信に失敗したリクエストを再試行するために、内部で workbox-background-sync を使用しています。

どのようなユースケースでも、workbox-background-sync はこの種のタスクを簡素化して、デベロッパー エクスペリエンスを向上させ、ウェブ アプリケーションのユーザー エクスペリエンスと機能を改善する機会を提供します。