YASUHIRO
ポートフォリオのUX向上:bfcacheを活用したページ遷移の爆速化
Frontend

ポートフォリオのUX向上:bfcacheを活用したページ遷移の爆速化

自身のポートフォリオサイトを作成するにあたり、ユーザーにストレスなく閲覧してもらうため、「ページ遷移の高速化」は重要なテーマでした。様々なチューニングを試す中で、モバイルブラウザの強力なキャッシュ機能を活用・制御した事例を紹介します。

1. bfcacheによる「爆速」ページ遷移

iOS SafariやAndroid Chromeなどのモバイルブラウザには、「bfcache(Back/Forward Cache)」という前後ナビゲーションの高速化機能が搭載されています。戻る・進むボタンが押されたとき、ブラウザはHTTPリクエストを発行せず、JSの実行状態ごとフリーズしたスナップショットをメモリから一瞬で復元します。

2. 直面した課題:download.txt の発生

このbfcacheを活用しようとした際、一つ厄介な問題に直面しました。スマホで「戻るボタン→再遷移」をすると、突然 `download.txt` や `download.html` がダウンロードされてしまうのです。

原因はサーバーとクライアントの状態不一致

bfcacheから復元された「古い状態(セッション等)」のまま次のページへ遷移すると、サーバー側が状態不一致を検知してエラーレスポンスを返します。このレスポンスの Content-Type が適切でないと、スマホブラウザが強制的にファイルとしてダウンロードしてしまう仕様でした。

3. 高速化と安全性の両立(実装した解決策)

単にキャッシュを無効化(no-store)すればバグは直りますが、それでは高速化の恩恵を受けられません。そこで、基本はbfcacheを利用しつつ、裏側で安全性を担保する仕組みを実装しました。

  1. 1pageshow イベントの e.persisted で bfcache からの復元を検知
  2. 2復元された瞬間に、裏側でAPIを叩いて「最新のバージョン」をチェック
  3. 3バージョンが同じなら、bfcacheの高速な表示をそのまま維持
  4. 4バージョンが変わっていた場合のみ、強制リロードして状態を最新化
const handlePageShow = async (e: PageTransitionEvent) => {
  if (!e.persisted) return
  console.log('[CacheReloader] bfcache restore detected, checking version...')
  
  const latest = await fetchVersion()
  if (!latest) return // ネットワーク失敗時は現状維持

  if (currentVersion.current && latest !== currentVersion.current) {
    // バージョン変更検出:安全のためにリロード
    window.location.reload()
  } else {
    // バージョン同一:bfcacheの高速復元をそのまま活用!
    currentVersion.current = latest
  }
}
window.addEventListener('pageshow', handlePageShow)

この実装により、不要なリロードを抑えてポートフォリオのページ遷移をサクサクに保ちつつ、予期せぬダウンロードバグを防ぐという、UXと安定性を両立させることができました。

Qiitaで詳細を見る