代表的な面接トピック

フロントエンド面接:アセットの不整合を起こさずにService Workerを安全に更新する方法

フロントエンド難しい
Offer.cc 編集チーム公開日 更新日

質問

PWAのデプロイ後に一部のユーザーで古いJavaScriptと新しいHTMLが混在し、ChunkLoadErrorが発生しています。Service Workerがwaiting状態になる理由を説明し、安全なバージョニング、キャッシュクリーンアップ、ユーザープロンプト、オブザーバビリティ、およびロールバックを設計してください。

プロンプトとコンテキスト

PWAのリリース後、一部のユーザーが依然として古いService Workerによって制御され、新しいHTMLとともに古いJavaScriptを読み込むことでChunkLoadErrorが発生しています。ライフサイクル、キャッシュバージョン、開いているタブ、skipWaiting、clientsClaim、およびロールバックのトレードオフを説明してください。

この質問は、フロントエンド、ウェブプラットフォーム、およびフルスタックの職種に適しています。特定のフレームワークに依存せず、デプロイの安全性とユーザーエクスペリエンスをテストします。エラー率や古いキャッシュの比率は実践データであり、普遍的なしきい値ではありません。

面接官がテストしていること

ライフサイクル

候補者は、install、waiting、activate、およびページ制御について、特に古いクライアントが開いたままの間、更新されたworkerが待機する理由を説明できる必要があります。

アセットの一貫性

HTML、ハッシュ化されたJavaScript、ランタイムAPIデータ、およびprecacheエントリを分離します。古いキャッシュを削除した結果、そのアセットをまだ参照しているページが破損してはなりません。

適用戦略

skipWaitingは適用を早めることができますが、ページのライフタイム中に制御が切り替わる可能性があります。優れた回答では、互換性とユーザーの同意を評価します。

ロールバックとオブザーバビリティ

バージョンID、有効期限ウィンドウ、エラー監視、およびno-op workerにより、問題のあるロールアウトを停止する手段を提供します。

最初に確認すべき質問

  • HTMLと静的アセットはコンテンツハッシュを使用していますか?
  • Service WorkerのURLとスコープは安定していますか?
  • ユーザーがページを数時間開いたままにしたり、未保存の状態を持ったりする可能性はありますか?
  • APIは両方のクライアントバージョンと後方互換性がありますか?
  • プロダクトは安全なタイミングでリフレッシュを促すプロンプトを表示できますか?
  • プラットフォームはworkerスクリプトとアセットマニフェストを迅速にロールバックできますか?

30秒の回答

「更新されたworkerは通常、install後にwaiting状態に入り、その間は古いworkerが開いているページを制御し続けます。私ならまず、HTML、ハッシュ化されたアセット、およびAPIコントラクトのバージョン互換性を確保し、その上でskipWaitingが許容できるかを判断します。リビジョン管理されたprecacheエントリを使用し、activate中に古いことが明らかなキャッシュのみを削除します。

ページ側ではupdatefoundとcontrollerchangeを監視し、安全なときにリフレッシュを促し、workerのバージョン、ChunkLoadError、およびアクティベーション時間を記録します。問題のあるリリースの場合は、以前のアセットを保持したままロールアウトを停止するかno-op workerを配信し、修正して段階的に進めます。」

ステップごとの詳細な回答

ステップ1:ライフサイクルを描く

登録によりinstalling状態のworkerが作成されます。install後はwaiting状態になりますが、既存のページは依然として古いworkerが制御します。古いクライアントが閉じられるかナビゲーションが発生すると、新しいworkerがactivateされて制御を引き継ぎます。

ステップ2:アセットの互換性を確保する

HTMLはハッシュ化されたアセットを参照し、APIは移行期間中に古いフィールドを許容する必要があります。古いページが削除されたチャンクを要求する場合、キャッシュ名だけを変更しても解決になりません。

ステップ3:更新チェックを設計する

workerのURLは固定しておきます。ブラウザはナビゲーション時や登録時にバイト単位の変更をチェックします。長時間のセッションではregistration.updateを明示的に呼び出してもよいですが、過剰なポーリングは避けるべきです。

~~~js const registration = await navigator.serviceWorker.ready; await registration.update(); ~~~

ステップ4:待機とプロンプトを処理する

デフォルトではwaitingが最も安全です。即時適用が必要な場合は、未保存の状態やプロトコルの互換性を確認し、ユーザーに確認した上で、制御されたメッセージ経由でskipWaitingを送信します。リフレッシュループを発生させずにcontrollerchangeを処理します。

ステップ5:キャッシュのクリーンアップとロールバック

activate中には、許可リストに含まれないキャッシュのみを削除します。ロールバック用に以前のアセットウィンドウを保持します。リリースに問題がある場合は、すべてのキャッシュを削除するのではなく、エントリーポイントをロールバックするかno-op workerを配信します。

ステップ6:監視と検証

workerのバージョン、キャッシュヒット、アクティベーション時間、controllerchange、アセットの404、およびChunkLoadErrorを記録します。古いタブと新しいタブ、オフライン起動、リフレッシュ、段階的ロールアウト、およびロールバックをテストします。

模範回答

「ChunkLoadErrorは、ページが参照しているチャンクがデプロイによって既に削除されているにもかかわらず、古いworkerがそのページを制御している場合に発生することがあります。新しいworkerはデフォルトで待機するため、最初にいきなりグローバルでskipWaitingを呼び出すことはしません。

workerのURLを安定させ、ハッシュ化されたアセットを使用し、APIの互換性ウィンドウを維持します。precacheのリビジョンは明示的に管理し、activate時には許可リストから外れた古いキャッシュのみを削除します。ページ側では待機中のworkerを検出し、未保存の状態がない場合にリフレッシュを提案します。即時切り替えには、互換性と慎重なcontrollerchangeの処理が必要です。

リリースは段階的に行い、workerのバージョン、アセットの404、およびChunkLoadErrorを監視します。バージョンに問題がある場合は、エントリーポイントのロールアウトを停止するか、古いアセットを保持したままno-op workerをデプロイします。リカバリでは、複数タブ、オフライン起動、リフレッシュ、および完全なロールバックをカバーする必要があります。」

よくある間違い

  • installによってすぐにすべてのページが制御されると思い込むこと。
  • ハッシュ化されていないJavaScriptをその場で上書きすること。
  • 無条件にskipWaitingを呼び出し、ページの途中でバージョンを混在させること。
  • activate中にすべてのキャッシュを削除すること。
  • 更新を強制するためにworkerスクリプトの名前を変更すること。
  • 開いたばかりのページのみをテストし、長時間開いたタブをテストしないこと。
  • フロントエンドのエントリーのみをロールバックしてAPIを破損させること。
  • workerバージョンのテレメトリやno-opロールバックを用意していないこと。

フォローアップの質問

フォローアップ1:なぜ新しいworkerは待機するのですか?

古いworkerがまだ開いているクライアントを制御しているためです。制御が予期せず切り替わらないように、デフォルトのライフサイクルではそれらのクライアントが閉じるかナビゲーションするのを待ちます。

フォローアップ2:skipWaitingが妥当なのはどのような場合ですか?

アセットとAPIに後方互換性があり、未保存の重要な状態がなく、即時リフレッシュが許容される場合です。それ以外の場合は、ユーザーの同意またはナビゲーションを待ちます。

フォローアップ3:キャッシュの無制限な増加をどのように防ぎますか?

バージョンやリビジョンの許可リストを使用し、activate中に未使用のキャッシュのみを削除します。定義されたロールバックウィンドウの間、以前のリリースのキャッシュを保持します。

フォローアップ4:バグのあるworkerをどのように停止しますか?

エントリーのロールアウトを停止し、必要に応じてno-op workerをデプロイするか、正常であることが確認されているスクリプトを復元します。リリースを修正する間、古いアセットを利用可能な状態に保ちます。

フォローアップ5:更新が安全であることをどのように証明しますか?

複数タブ、オフライン起動、新しいアセットと古いHTMLの組み合わせ、リフレッシュ、更新プロンプト、API互換性、エラー監視、および完全なロールバックパスをテストします。

公開情報ソース

関連する質問