拡張機能メッセージ ポートを使用した BFCache の動作の変更

バックフォワード キャッシュ(BFCache)は、すぐに前後に移動できるブラウザの最適化です。Google は Chrome BFCache に変更を加えます。この変更は、メッセージ ポートを使用する拡張機能に影響する可能性があります。メッセージを使用してコンテンツ スクリプトと拡張機能間の通信を行う Chrome 拡張機能をお持ちの場合は、拡張機能をテストして調整する方法をご確認ください。

拡張機能のメッセージ ポート

拡張機能は、メッセージの受け渡しを介してコンテンツ スクリプトや他の拡張機能と通信します。メッセージを送信するには、runtime.sendMessage()tabs.sendMessage() を呼び出す 1 回限りのリクエストを使用するか、再利用可能なメッセージ ポートを使用します。ポートがアクティブである限り、コンテンツ スクリプトと拡張機能のバックグラウンド スクリプトの両方で、ポートを再利用して相互にメッセージを投稿できます。

詳しくは、メッセージの受け渡しをご覧ください。

バックフォワード キャッシュ

BFCache の対象のページから移動する場合、ブラウザはすべての状態のページをメモリに残したまま、完全アクティブでない状態のままにします。ユーザーがキャッシュ ページまで履歴移動(戻るまたは進む)を行うと、ブラウザは BFCache からページの復元を試みます。これにより、ナビゲーションが速くなり、ユーザーのブラウジング エクスペリエンスが向上します。

ページが BFCache にある間は、JavaScript の実行が許可されていないフリーズ状態になります。つまり、受信したメッセージは処理できません。

詳細については、バックフォワード キャッシュをご覧ください。

拡張機能のメッセージ ポートが BFCache に及ぼす影響

要するに、BFCache 内のページにメッセージを送信する拡張機能は、キャッシュ エビクションを引き起こし、パフォーマンスに影響を与える可能性があります。

拡張機能のメッセージ ポートが開いているページが BFCache に保存されている場合、ポートは開いたままになります。ページが BFCache から復元された後も、拡張機能 Service Worker はメッセージ ポートの古い参照を使用してメッセージをコンテンツ スクリプトに送信できます。

ただし、ページが BFCache に残っている間に拡張機能がそのメッセージ ポートを介してメッセージを送信しようとすると、メッセージは送信されますが、ハンドラがフリーズされるため、完全には配信されません。メッセージのキューイングとドロップにはそれぞれ固有の問題があるため、拡張機能がこの状況を理解して対処することは困難です。

メッセージが失われることによる問題を回避するため、Chrome の現在の実装では、ホストページを BFCache から強制排除し、メッセージは破棄しています。ユーザーがページに戻ると、そのページは新たに読み込まれ、拡張機能が新しい接続を設定できるようになります。

一方、この実装は BFCache が適用されるシナリオを制限し、特にすべての接続に定期的にメッセージを送信するブロードキャスト メカニズムまたはハートビート メカニズムを使用する拡張機能ではパフォーマンスの向上が制限されます。さらに、拡張機能がコンテンツ スクリプトにメッセージを送信したときにエビクションがトリガーされるため、ウェブ デベロッパーはページの削除を防ぐ手段も用意できません。

全体的なパフォーマンスを向上させるために、新しいメッセージ ポートの動作を導入する予定です。

新しい動作: ページが BFCache に保存されているときにメッセージ チャネルを閉じる

Chrome 123 以降では、拡張機能のメッセージ ポートが開いているページが BFCache に保存されると、基になるメッセージ チャンネルがコンテンツ スクリプト側からプロアクティブに閉じられます。その結果、すべてのメッセージ ポートが閉じ、拡張機能は onDisconnect イベントを受け取ります。

チャンネルが閉鎖されているため、BFCache の間はページにメッセージは送信されません。拡張機能によってページが強制排除されることはありません。

ページが BFCache から復元された後も、閉じられたメッセージ チャネルは再開されません。拡張機能の作成者は、ページのライフサイクル イベントをリッスンし、ページが BFCache から復元されたときに新しい接続を設定することをおすすめします。次の例をご覧ください。

// content script

let port;

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // The page is restored from BFCache, set up a new connection.
    port = chrome.runtime.connect();
  }
});

詳しくは、各ブラウザの代表者からの WECG の会話(Issue 474)をご覧ください。

影響

新しい動作は Chrome 123 でフラグの背後で有効になるため、コードをテストできます。詳しくは、タイムラインをご覧ください。以下の手順に沿って拡張機能をテストします。あくまで簡単なテストです。拡張機能のどの機能が問題を引き起こすかを予測することは難しいため、この機能は一定期間有効にして Chrome を実行することをおすすめします。

  1. Chrome のバージョンが 123 以降であることを確認します。理想的には、テストを容易にするために追加の警告が表示される Chrome Canary を使用してください。
  2. 次のフラグを指定して Chrome を起動します。

    --disable-features=DisconnectExtensionMessagePortWhenPageEntersBFCache
    
  3. 拡張機能を実行せずに BFCache の対象となるページに移動します(たとえば、https://example.com/ のようなシンプルなサイト)。BFCache のチュートリアルに沿って、BFCache から復元されることを確認します。

  4. 拡張機能をインストールして有効にし、BFCache の対象をもう一度テストします。手動で移動し、拡張機能が BFCached のページにメッセージを投稿するのに十分な時間が経過してから、戻ることができます。

  5. エビクションによりページを BFCache ではなく新たに読み込む必要があり、復元を妨げる問題が「ExtensionSentMessageToCachedFrame」である場合、この変更によって拡張機能が影響を受ける可能性があります。

    Chrome Canary 124.0.6315.0 以降では、ページに次の警告も表示されます。

    ページが BFCache から復元されない場合に表示される警告。
    ページが BFCache から復元されない場合に表示される警告。

拡張機能によって BFCache ページにメッセージが投稿されていることを確認したら、以下の手順でテストを強制的に有効にし、ロジックに問題がないかどうかを確認できます。

  1. 次のフラグを指定して Chrome を起動します。

    --enable-features=DisconnectExtensionMessagePortWhenPageEntersBFCache
    
  2. 「ExtensionSentMessageToCachedFrame」が原因で BFCache から復元されなかったページに移動します。

  3. 移動して戻ります。これでページは復元されましたが、コンテンツ スクリプトと Service Worker の間のメッセージ チャネルは切断されています。

  4. 拡張機能が通常どおりに機能するかテストします。動作しない場合は、前のセクションで説明したように手動で再接続する必要があります。

リリース スケジュール

Chrome 123 以降、新しい動作を段階的に導入する予定です。計画の詳細は次のとおりです。

日付 計画されたマイルストーン
2 月 15 日 Chrome Canary と Dev で、新しい動作のテストを開始します。
3 月 1 日 Chrome Beta で新しい動作のテストを開始します。
3 月 18 日 Chrome Stable 版で、ユーザーの 4% に対して新しい動作をリリースします。
3 月 25 日 Chrome Stable 版で、50% のユーザーに新しい動作をリリースします。
4 月 2 日 テストが終了し、新しい動作がデフォルトになります。