⏪ Chrome 149でWebSocketがBFCacheの敵ではなくなった — 「戻る」を最速にする2026年の作法

WebSocket接続があるとBFCache不適格、という常識がChrome 149で変わった。自動切断+pageshow再接続の新しい作法と、自サイトでのBFCache検証・方向付きView Transitionの実装をまとめる。

読む深さ

「戻る」ボタンは、Webでいちばん押されているのに、いちばん最適化されていないボタンだと思う。

高速化の主戦場はずっと初回ロード(LCP)だったが、実際のユーザーは行って戻ってを繰り返す。そこで効くのがBFCache(バック/フォワードキャッシュ)——戻る/進むのときにページを再読み込みせず、メモリ上のスナップショットをJSの実行状態ごと丸ごと復元する仕組みだ。効いていれば戻るは実質0msになる。

このBFCacheに、Chrome 149(2026年6月2日にStable)で大きめの変更が入った。日本語ではまだほぼ解説が無いので、自サイトでの検証と合わせてまとめておく。

WebSocketが「不適格条件」から外れた

これまでWebSocket接続を張っているページは、BFCacheの対象外だった。接続を維持したままメモリに凍結するわけにいかないので、まるごと諦める仕様だったわけです。チャットやダッシュボードのような「常時接続系のアプリほど戻るが遅い」という皮肉な状況がずっとあった。

Chrome 149からは、BFCache進入時にWebSocketを自動切断したうえでキャッシュに乗せる方向に変わった。ページは凍結保存され、復帰時にアプリ側で再接続する。検知はこう書く。

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // BFCacheからの復帰。ここでWebSocketを再接続する
    reconnect();
  }
});

persistedtrue なら再読み込みではなくBFCache復帰だ。逆に退避側は unload ではなく pagehide を使う。unloadハンドラは今でもBFCache不適格の代表格なので、残っていたら真っ先に消す対象になる。

適格条件の現在地を整理すると、WebSocketは149で解禁、Cache-Control: no-store のページも条件付き(TTL 3分)で解禁済み。一方 unload ハンドラと WebRTC 接続は依然として不適格のままだ。

自サイトで検証してみた

このサイト(静的Astro)でBFCacheが本当に効いているか、Chrome DevTools MCP経由で確かめた。手順は単純で、pageshow リスナーを仕込んでから外部サイトへ移動し、戻ってきてフラグを見るだけ。

window.addEventListener('pageshow', (e) => {
  window.__bfPersisted = e.persisted;
});
// 外部サイトへ移動 → 戻る → window.__bfPersisted を確認

結果は true。リスナーを含むJSの状態が生きたまま返ってきているので、復元であって再読み込みではない。DevToolsを繋いだままでも効いていたのは意外だった(昔は計測しようとすると無効化される、が定説だった)。解析ビーコンくらいの軽い外部スクリプトなら阻害しないことも確認できた。

ついでに「戻る」の方向をCSSに教えた

BFCacheが速さを担当するなら、View Transitionは気持ちよさの担当だ。Astroのルーターは戻る操作のときに <html data-astro-transition="back"> を付けてくれるので、CSSだけで進むと戻るのアニメーション方向を反転できる。

::view-transition-old(content) { animation: vt-out-fwd 0.15s ease-in both; }
::view-transition-new(content) { animation: vt-in-fwd 0.22s ease-out both; }

/* 戻る操作のときだけ逆方向に */
[data-astro-transition='back']::view-transition-old(content) { animation-name: vt-out-back; }
[data-astro-transition='back']::view-transition-new(content) { animation-name: vt-in-back; }

コツは main にだけ view-transition-name を付けて、ヘッダーを動かさないこと。全画面をスライドさせるとヘッダーまで毎回泳いで、うるさくなる。JSはゼロ、prefers-reduced-motion の人には出さない。

念のため書いておくと、「戻るボタンを無効化して離脱を防ぐ」系のハックは、履歴スパム対策としてブラウザ側が既に潰している。この領域で残っているのは、戻るを速く・気持ちよくする方向だけだ。

初回ロードの最適化はもうコモディティになった。次に差が付くのは2回目以降の体験——つまり戻る/進むだと思っている。あなたのサイト、pageshowpersisted: true、返ってきますか。3行で確かめられるので、ぜひ手元で。

元ネタ: https://developer.chrome.com/blog/new-in-chrome-149