Service Workerはページと別の実行コンテキストでネットワークやキャッシュ処理を行えますが、登録直後にすべてのページを制御するわけではありません。ブラウザーはinstall、waiting、activateなどのライフサイクルを管理します。以前のworkerが制御するページが残っていると、新しいworkerの有効化が遅れることがあります。この順序を知ると、更新を配布しても開いたタブで以前の動作が続く理由を理解できます。

二つのページ版とService Worker切り替えの概念図

概念図であり実際のブラウザー画面や測定時間ではありません。

1. 登録からinstall、activateまで

ページはHTTPSなどのセキュアコンテキストでService Workerを登録し、ブラウザーはスクリプトを取得してinstallを試みます。installイベントでは初期キャッシュを準備したり、失敗を処理したりできます。インストールが成功しても、必ず直ちに既存workerを置き換えるわけではありません。通常は以前のworkerがregistration配下のクライアントを制御していれば、新workerはwaiting状態に残ることがあります。

既存クライアントの制御終了は、ライフサイクルや未完了イベントの条件に従って有効化を可能にします。activateでアプリ所有のCacheStorageを整理できますが完了は保証されません。HTTPキャッシュとは別です。これらは順序が定義されたブラウザー管理の段階であり、通常の処理キューのようにアプリケーションが常に自由に飛ばせるものではありません。

2. waitingが更新を安全にする理由

waitingはページの存続中に異なるworker版から資源を読み込む混在を減らすために役立ちます。新しいworkerがキャッシュ形式やメッセージ方式を変えると、古いページと新しいworkerの組み合わせで予期しない結果が生じることがあります。既存クライアントの制御が終わるまで待つことで、段階的な切り替えを安全にしやすくなります。

そのため更新後も、すでに開いているタブでは以前のファイルや動作が続くことがあります。常に更新失敗を意味するわけではありません。アプリケーションは待機中の版を検知して利用者と切り替え時点を決められます。移動中のクライアントが重なるため、再読み込みだけでは有効化を保証できません。入力中のページを強制再読み込みして作業を中断しないようにします。

3. skipWaitingとclients.claimの変更点

skipWaiting()は有効化を要求し、installを省略せず同期的に引き継ぎを完了しません。有効化は既に制御されたクライアントを移します。有効化中を含むactive workerはclients.claim()でregistrationとscopeに合う適格なクライアントを制御できます。置き換えの引き継ぎにclaimは必須ではありません。更新を早く適用できますが、古いページが期待する資源やプロトコルと新workerの動作が異なる危険も高まります。どちらも自動的な安全機能ではありません。

即時切り替えが必要なら、キャッシュの版、要求形式、メッセージ互換性を考慮し、古いページと新workerの組み合わせを試験します。HTMLと静的資産が異なるリリースから配信される中間状態も扱う必要があります。迅速な引き継ぎの明確な理由がなければ既定のwaitingを保ち、利用者が安全な再読み込み時点を選べるようにします。

4. 専門家の視点:更新状態を観測する

Service Worker仕様は登録、install・waiting・activateの流れ、クライアント制御の規則を定めています。MDNはscopeとブラウザー管理を説明します。Jake Archibaldの当時の解説は初回ページの制御と版の混在リスクを強調します。各ページが制御されるかはregistrationとcontrollerの関係によるため、新しいworkerファイルの配布だけでは開いているすべてのタブが即座に更新されたと判断できません。

運用では更新のインストール、waiting、active controllerの状態を作業を妨げない形で示します。初回訪問、旧タブを開いたままの更新、複数タブ、オフライン切り替え、install失敗と再試行を試験してください。skipWaiting()やclients.claim()は互換性を確認し、早い切り替えが必要な場合に限って使います。重要な入力中に強制的に制御を移さないようにします。ライフサイクルを観測すればサポート問題やキャッシュ動作を調査しやすくなります。

参考資料