feat: PWA更新検知時のoverlay+自動reloadをmypace方式で実装#52
Merged
Conversation
install時の無条件self.skipWaiting()を廃止し、SKIP_WAITINGメッセージ受信時のみ skipWaitingするよう変更。既存タブが古いSWに制御されている「更新」ケースでのみ 影響し、初回インストールは制御元が無いため従来どおり即activateされる。 クライアント側が作業中でないか確認してから明示的に切り替えを許可できるようにする。
角調整・比較・GIF/動画生成・保存など、ImageProcessorのphaseがuploadでない間は 未保存の作業がある。lib/appBusy.tsのグローバルbusyフラグをImageProcessorが 更新し、SW更新ハンドラ側でwaitUntilIdle()により作業完了までreloadを遅延できる ようにする。
ServiceWorkerRegisterでupdatefound→新workerのstatechangeで更新を検知し、 overlay表示→postMessage(SKIP_WAITING)→controllerchange待ちreload (fallback 2秒)→sessionStorage cooldown(10秒)というmypaceと同等の流れを 実装。overlay文言はlib/i18n.tsxにpwaUpdateRestarting(ja/en)として追加。 useI18n()で言語判定するためServiceWorkerRegisterを両layout.tsxの I18nProvider内に移動(/enの言語判定に必要)。
updatefound/statechangeが短時間に複数回発火すると、cooldownのsessionStorage 書き込みがwaitUntilIdle()のawait後にあるため、複数のapplyUpdate呼び出しが cooldownチェックを素通りしてidle待機中に並走し得た。overlay二重生成・ SKIP_WAITING二重postMessage・controllerchangeリスナー二重登録・reloadタイマー 二重セットにつながる。 モジュールレベルのapplyingフラグを追加し、関数先頭で多重実行を防止。 cooldownチェック通過後にフラグを立て、reload成功パスでは戻さない (reloadでモジュール状態ごと消える)が、cancelledによる中断パスでは 確実にリセットする。
Deploying machigai-salad with
|
| Latest commit: |
4f842e5
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://c4b648f7.machigai-salad.pages.dev |
| Branch Preview URL: | https://51-pwa-update-reload.machigai-salad.pages.dev |
独立レビュアーのmust指摘2件に対応(姉妹リポorberの同種修正を参考)。 must 1: mount時に既にwaiting/installingの新SWがある場合を検知できない updatefoundは新規installingの開始時にのみ発火し、既にinstall完了して waitingにいる、またはinstalling中のworkerには再発火しない。ブラウザは ナビゲーション時に自前でSW更新チェックを行うため、React hydration→ useEffect実行より前にこの更新チェックが完了しているケースは通常の デプロイ後リロードで十分起こり得、その場合更新が握りつぶされていた。 → mount時にregistration.waiting/installingの両方を確認するように変更。 must 2: overlay表示〜reloadの間、再開した作業をチェックする手段が無い 「overlayが操作をブロックするから再チェック不要」という設計判断を撤回。 overlayはpointer操作は塞ぐがfocus/keyboard入力や既に走っている非同期 処理までは止めないため、pre-delay(1.5秒)+fallback(2秒)の間にbusy状態へ 戻り得る。 → postMessage送信直前・controllerchangeハンドラ内・fallbackタイマー内で isAppBusy()を再チェックし、busyならidle復帰を待って自動的に続行する makeIdleGatedOnce()を導入。 テスト容易性のため、この2件の判定ロジックをServiceWorkerRegister.tsx ('use client'のDOM依存コンポーネント)からlib/swUpdateDetection.tsへ 純粋関数として切り出し(vitest.config.tsがnode環境・*.test.ts限定なため、 DOM/Reactコンポーネントは直接テストできない制約に対応)。 lib/swUpdateDetection.test.tsで両must項目の回帰テストを追加。
独立レビュアーの追加must指摘に対応。
ServiceWorkerRegisterの登録用useEffectが[t](useI18n()のcallback、
langが変わるたびに再生成される)に依存していた。/ をブラウザ言語が
日本語以外の訪問者が開くと、auto-detectでlangが'ja'→'en'に切り替わり
tの参照が変わってeffectが再実行される。cleanupはcancelled=trueを
セットするだけでregistration.removeEventListener('updatefound', ...)を
呼ばないため、同じregistrationに2つのupdatefoundリスナーが残る。
実update時に両方が同期的に発火し、モジュールレベルのapplyingフラグの
奪い合いにより、cancelled側が先にapplyingを取ってしまうケースで
どちらの経路も更新を完走させず、更新がサイレントにドロップされる
(前回must1/2で追加した機構を無効化する回帰)。
→ 登録・リスナー設定用のeffectをtに依存させず一度だけ実行するよう
修正。overlay文言用のtはuseRefで最新値を保持して参照する形に変更。
ServiceWorkerRegister.test.tsを追加。TypeScriptコンパイラAPIで
ソースを解析し、登録effectの依存配列が空であることと、tRef.current
経由で翻訳関数を参照していることを構造的に検証する回帰テスト
(DOM/RTL環境が無いため、コンポーネントの直接レンダリングではなく
ソース形状の静的検証)。修正前のコードに対して実行し、実際に
テストが失敗することを確認済み。
docs/architecture.mdのPWA更新方針節とdocs/changelog.mdを、mount時
検知・busyの3箇所再チェック・lib/swUpdateDetection.tsへの切り出し・
今回のeffect依存修正に追従させた。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
関連 Issue
Refs #51(実機/build previewでの動作確認が完了するまでopenのまま)
変更内容
public/sw.jsのskipWaitingをmessage駆動に変更(初回インストールは従来通り自動、更新時のみクライアント承認を待つ)lib/appBusy.ts(新規)で作業中(撮影後の調整・比較・書き出し等)はreloadをdeferするゲートを追加components/ServiceWorkerRegister.tsxを overlay→postMessage→controllerchange reload→fallback→cooldown のフローに書き換え/enルートでoverlay文言が正しく英語になるようServiceWorkerRegisterの配置を修正applyUpdate多重発火防止フラグを追加既知のギャップ
vitest.config.tsがenvironment: 'node'限定("Pure-logic helpers only")のため、ServiceWorkerRegister.tsx/ImageProcessor.tsx本体(今回のQA修正=多重発火防止フラグを含む)はunitテスト化できていません。純粋ロジック(appBusy.ts,sw.js)はカバー済み