1. ホーム
  2. javascript

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

2023-08-19 16:48:20

質問

私は自分のコンピュータでサービスワーカーAPIを使って遊んでいます。

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

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

ありがとうございます!

どのように解決するのですか?

私は、ここでの他の回答のいくつかを拡張して、「必要な変更を確実に行うために、サービス ワーカーを本番環境にロールアウトするときにどのような戦略を使用できますか」という観点からこれに取り組みたいと思いました。これらの変更には、実運用環境で発見したマイナーなバグの修正が含まれるかもしれませんし、乗り越えられないバグによってサービス ワーカーを無効にすること (いわゆる「キルスイッチ」) が含まれるかもしれません (そうでないことを願っていますが)。

この回答の目的では、次のように呼び出すと仮定します。

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

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

の最初の問題をどのように解決するかに集約されます。 service-worker.js コードの最初の問題をどのように解決するかということです。もしそれが小さなバグフィックスであるなら、明らかに変更するだけで、あなたの service-worker.js をホスティング環境に再展開することができます。明らかなバグ修正がなく、解決に時間がかかっている間、バグだらけのサービス ワーカー コードを実行しているユーザーをそのままにしておきたくない場合。 を使うのは良いアイデアです。 no-op service-worker.js ハンディ を、以下のようにします。

// 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);
    });
  });
});
*/

これであなたのノーオペの service-worker.js を含む必要があります。なぜなら fetch ハンドラが登録されていないため、制御されたページからのすべてのナビゲーションとリソースのリクエストは、ネットワークに対して直接行われることになり、サービスワーカーが全くない場合と同じ動作になります。

追加のステップ

さらに踏み込んで、"apartment "メソッドを使って保存されているものをすべて強制的に削除することも可能です。 キャッシュ ストレージ API を使うか、あるいは サービスワーカーを明示的に登録解除する を完全に解除することもできます。ほとんどの一般的なケースでは、これはおそらくやりすぎで、上記の推奨事項に従って、現在のユーザーが期待される動作を得られる状態にし、バグを修正したら更新を再展開する準備を整えるのに十分なはずです。何もしないサービスワーカーを起動するにもある程度のオーバーヘッドが発生しますから、次のようなルートを取ることもできます。 サービスワーカーの登録を解除する を実行することもできます。

すでにサービスしている状況であれば service-worker.js を HTTP キャッシュディレクティブによって、 ユーザの待ち時間よりも長い有効期限で提供しているのであれば、 シフト + リロード は、サービス ワーカーの制御外でページの再読み込みを強制することに留意してください。すべてのユーザーがこの方法を知っているわけではありませんし、モバイル機器では不可能ですが。そのため、実行可能なロールバックプランとして Shift + Reload に依存しないようにしてください。

サービスワーカーの URL がわからない場合はどうすればよいですか?

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

まず、今後はこれを避けるようにしましょう。 ベストプラクティスに反する . しかし、すでに多くのバージョン管理されたサービスワーカー URL をデプロイしており、その中で すべて ユーザーを無効にする必要がある場合、どの URL で登録したかに関係なく、解決する方法があります。

ブラウザがサービス ワーカー スクリプトにリクエストを行うたびに、それが初期登録であるか更新チェックであるかに関係なく、HTTP リクエスト ヘッダである Service-Worker: .

バックエンドの HTTP サーバを完全に制御できると仮定すると、 受信したリクエストにこの Service-Worker: ヘッダがあるかどうかを確認し、リクエスト URL が何であるかに関係なく、常にサービスワーカー スクリプトのレスポンスで応答することができます。

これを行うための Web サーバーの設定の詳細は、サーバーによって異なります。

Clear-Site-Data: レスポンスヘッダ

最後の注意点: いくつかのブラウザは、特別な HTTP レスポンスヘッダがレスポンスの一部として返されると、特定のデータを自動的に消去し、サービスワーカーを登録解除する可能性があります。 Clear-Site-Data: .

このヘッダを設定すると、不適切なサービスワーカーのデプロイから回復しようとするときに役立ちます。キルスイッチのシナリオは、この機能の 仕様に含まれています。 に使用例として含まれています。

を確認することが重要です。 ブラウザサポートストーリー には Clear-Site-Data: の前に もっぱら をキルスイッチとして利用することをお勧めします。2019年7月現在、サービスワーカーをサポートするブラウザの100%でサポートされていないため、現時点では、最も安全なのは Clear-Site-Data: を、すべてのブラウザで不具合のあるサービスワーカーからの復旧に不安がある場合は、上記のテクニックとともに使用するのが最も安全です。