web-dev-qa-db-ja.com

バグのあるサービスワーカーを削除したり、「キルスイッチ」を実装するにはどうすればよいですか?

私は自分のコンピューターでService Worker APIで遊んでいるので、実世界のアプリでどのようにそれから利益を得ることができるかを把握できます。

fetchイベントをインターセプトするサービスワーカーを登録して、要求を送信する前に要求されたコンテンツのキャッシュをチェックできるという奇妙な状況に遭遇しました。問題は、このコードにエラーがあり、関数がリクエストを実行できなかったため、ページが空白のままになっていることです。何も起こりません。 Service Workerが登録されているため、2回目にページをロードすると、最初のリクエスト(HTMLをロードするリクエスト)がインターセプトされます。このバグがあるため、フェッチイベントが失敗し、HTMLを要求することはなく、空白ページが表示されます。

この状況で、悪いサービスワーカースクリプトを削除する唯一の方法は、chrome://serviceworker-internals/ コンソール。このエラーがライブWebサイトに到達した場合、それを解決する最善の方法はどれですか?

ありがとう!

44
PaquitoSoft

ここで他の回答のいくつかを拡張し、「サービスワーカーを運用環境に展開して必要な変更を確実に行えるようにするために使用できる戦略」の観点からこれにアプローチしたいと思いましたか?これらの変更には、実稼働環境で発見した小さなバグの修正が含まれる場合がありますが、乗り越えられないバグ(いわゆる「キルスイッチ」)によるサービスワーカーの無効化が含まれる場合もあります。

この答えの目的のために、あなたが電話すると仮定しましょう

navigator.serviceWorker.register('service-worker.js');

ページ上で、サービスワーカーのJavaScriptリソースがservice-worker.jsであることを意味します。 (使用された正確なService Worker URLがわからない場合は、以下を参照してください。おそらく、Service Workerスクリプトにハッシュまたはバージョン情報を追加したためです。

質問は、service-worker.jsコードの最初の問題をどのように解決するかということになります。小さなバグ修正であれば、明らかに変更を加えて、service-worker.jsをホスティング環境に再デプロイするだけです。明らかなバグ修正がなく、ユーザーがソリューションを解決するために時間をかけながらバグのあるService Workerコードを実行したままにしたくない場合は、を維持することをお勧めしますシンプル、 no-opservice-worker.js handy、次のように:

// A simple, no-op service worker that takes immediate control.

self.addEventListener('install', () => {
  // Skip over the "waiting" lifecycle state, to ensure that our
  // new service worker is activated immediately, even if there's
  // another tab open controlled by our older service worker code.
  self.skipWaiting();
});

/*
self.addEventListener('activate', () => {
  // Optional: Get a list of all the current open windows/tabs under
  // our service worker's control, and force them to reload.
  // This can "unbreak" any open windows/tabs as soon as the new
  // service worker activates, rather than users having to manually reload.
  self.clients.matchAll({type: 'window'}).then(windowClients => {
    windowClients.forEach(windowClient => {
      windowClient.navigate(windowClient.url);
    });
  });
});
*/

これは、no-op service-worker.jsに含める必要があるすべてです。 fetchハンドラーが登録されていないため、制御されたページからのすべてのナビゲーションおよびリソースリクエストはネットワークに対して直接送信され、サービスワーカーがまったくいなかった場合と同じ動作を効果的に提供します。

追加の手順

さらに進んで、 Cache Storage API を使用して保存されたすべてを強制的に削除するか、 明示的にサービスworker を完全に登録解除することができます。ほとんどの場合、それはおそらくやりすぎになるでしょう。上記の推奨事項に従うことで、現在のユーザーが期待される動作を得ることができ、バグを修正したらアップデートを再デプロイする準備が整います。 。無操作のサービスワーカーであっても起動にはある程度のオーバーヘッドが伴うため、意味のあるサービスワーカーコードを再デプロイする計画がない場合は、 サービスワーカーの登録解除 のルートに進むことができます。

HTTPキャッシュディレクティブを使用してservice-worker.jsを提供し、ユーザーが待つことができるよりも長いライフタイムを提供している状況に既にいる場合は、 Shift + Reload デスクトップブラウザーでは、Service Workerの制御外でページを強制的に再読み込みします。すべてのユーザーがこれを行う方法を知っているわけではなく、モバイルデバイスでは不可能です。したがって、実行可能なロールバック計画としてShift + Reloadに依存しないでください。

Service WorkerのURLがわからない場合はどうしますか?

上記の情報は、Service Worker URLが何であるかを知っていることを前提としています。_service-worker.jssw.js、または事実上一定の何か。しかし、service-worker.abcd1234.jsなどの何らかのバージョン管理またはハッシュ情報をサービスワーカースクリプトに含めた場合はどうでしょうか。

まず第一に、将来これを避けるようにしてください。これは against best practice です。ただし、既に多数のバージョン化されたService Worker URLをすでにデプロイしており、 all ユーザーに対して登録するURLに関係なく、これらを無効にする必要がある場合は、解決方法があります。

ブラウザは、最初の登録か更新チェックかに関係なく、Service Workerスクリプトをリクエストするたびに、 Service-Worker: というHTTPリクエストヘッダーを設定します。

バックエンドHTTPサーバーを完全に制御できると仮定すると、このService-Worker:ヘッダーの存在について着信リクエストをチェックし、リクエストURLが何であるかに関係なく、no-opサービスワーカースクリプトレスポンスで常に応答できます。

これを行うためのWebサーバーの構成の詳細は、サーバーごとに異なります。

Clear-Site-Data:応答ヘッダー

最後の注意:一部のブラウザーは、特別なHTTP応答ヘッダーが応答の一部として返されると、特定のデータを自動的に消去し、潜在的にサービスワーカーの登録を解除します: Clear-Site-Data:

このヘッダーを設定することは、悪いService Workerの展開から回復しようとするときに役立ちます。また、キルスイッチシナリオは、ユースケース例として機能の specification に含まれています。

キルスイッチとして solely に依存する前に、Clear-Site-Data:browserサポートストーリー を確認することが重要です。 2019年7月の時点では、サービスワーカーをサポートするブラウザーの100%ではサポートされていないため、現時点では、障害のあるサービスからの回復が懸念される場合は、上記の手法と共にClear-Site-Data:を使用するのが最も安全ですすべてのブラウザのワーカー。

70
Jeff Posnick

これは実に厄介な状況であり、実稼働環境では発生しないことを願っています。

その場合、異なるブラウザーの開発者ツールを使用したくない場合は、chrome://serviceworker-internals/点滅ベースのブラウザの場合、またはabout:serviceworkersabout:debugging#workers将来)Firefoxでは、2つのことが思い浮かびます。

  1. サービスワーカーの更新メカニズムを使用します。ユーザーエージェントは、登録されたワーカーに変更があるかどうかを確認し、それを取得して、activateフェーズを再度実行します。したがって、潜在的に、serviceworkerスクリプトを変更し、奇妙な状況を修正(キャッシュのパージなど)して、作業を続行できます。唯一の欠点は、ブラウザーが1日になる可能性のあるワーカーを更新するまで待つ必要があることです。
  2. 何らかの種類のkill switchをワーカーに追加します。キャッシュなどのステータスを復元できる特別なURLをユーザーがアクセスできるように指定できます。

ブラウザのデータを消去してもワーカーが削除されるかどうかはわかりません。そのため、別の選択肢になる可能性があります。

8

Javascriptを使用してService Workerを「登録解除」できます。以下に例を示します。

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.getRegistrations().then(function (registrations) {
    //returns installed service workers
    if (registrations.length) {
      for(let registration of registrations) {
        registration.unregister();
      }
    }
  });
}
5
Prasanna Jathan

ライブの状況では、バイトレベルでサービスワーカーを変更する必要があります(たとえば、最初の行にコメントを入力する)および 24時間以内に更新されます 。 Chrome)のchrome:// serviceworker-internals /でこれをエミュレートできますUpdateボタンをクリックします。

これは、更新アルゴリズムのステップ9がフラグを設定してService Workerをバイパスするため、Service Worker自体がキャッシュされた状況でも機能するはずです。

3
Salva

これはテストしていませんが、ServiceWorkerRegistrationオブジェクトには nregister() および pdate() メソッドがあります。これはnavigator.serviceWorkerから取得できます。

navigator.serviceWorker.getRegistration('/').then(function(registration) {
  registration.update();
});

その後、アップデートはすぐに新しいサービスワーカーがいるかどうかを確認し、インストールされている場合はインストールする必要があります。これにより、24時間の待機期間がバイパスされ、このjavascriptが検出されるたびにserviceworker.jsがダウンロードされます。

3
Marco Tolk