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を利用しつつ、裏側で安全性を担保する仕組みを実装しました。
- 1pageshow イベントの e.persisted で bfcache からの復元を検知
- 2復元された瞬間に、裏側でAPIを叩いて「最新のバージョン」をチェック
- 3バージョンが同じなら、bfcacheの高速な表示をそのまま維持
- 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と安定性を両立させることができました。
