JavaScript BFCache (Back/Forward Cache) 上下頁/往返 快取

BFCache (Back/Forward Cache) 是一種瀏覽器優化技術,旨在讓使用者在點擊「上一頁」或「下一頁」時能實現「瞬間載入」。與傳統的 HTTP 快取不同,BFCache 會將整個頁面的完整狀態(包含 JavaScript 執行狀態、DOM 現狀等)保留在記憶體中。

當頁面從 BFCache 恢復時,它不需要重新下載資源或重新解析 HTML,而是直接從記憶體中還原,這對提升使用者體驗有極大的幫助。

BFCache 的工作原理

當使用者導向新頁面時,支援 BFCache 的瀏覽器不會銷毀目前的頁面,而是將其「凍結」並存入快取。

  • 暫停執行: 所有的定時器 (setTimeout)、正在進行的網路請求或動畫都會被暫停。
  • 狀態保留: 所有變數的值、輸入框的文字、捲動軸的位置都會被原封不動地保存。
  • 恢復執行: 當使用者回到該頁面時,瀏覽器只需將頁面「恢復」,JavaScript 會從剛才暫停的地方繼續執行。

如何檢測頁面是否來自 BFCache?

由於 BFCache 恢復時不會觸發 load 事件,開發者必須使用 pageshow 事件,並檢查 event.persisted 屬性。

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    console.log('此頁面是從 BFCache 恢復的');
    // 在這裡更新過時的資訊,例如購物車數量或登入狀態
  } else {
    console.log('此頁面是全新載入的');
  }
});

同理,當頁面進入 BFCache 時,會觸發 pagehide 事件:

window.addEventListener('pagehide', (event) => {
  if (event.persisted) {
    console.log('頁面即將進入 BFCache');
  } else {
    console.log('頁面即將被正常卸載');
  }
});

影響 BFCache 成功率的因素

瀏覽器非常希望能將頁面存入 BFCache,但有些開發者的行為會阻止這項優化:

1. 絕對避免使用 unload 事件

這是最常見的錯誤。只要頁面註冊了 unload 監聽器,瀏覽器為了安全起見(擔心卸載邏輯沒跑完),通常會直接禁用該頁面的 BFCache。

  • 建議做法: 使用 pagehide 取代 unload 來處理資料清理或分析統計。

2. Cache-Control: no-store 的改變

過去,設定 Cache-Control: no-store 的頁面會被強制禁用 BFCache。

  • 最新趨勢: 2025 年起,Chrome 等瀏覽器開始嘗試在「安全」的情況下讓 no-store 頁面也能進入 BFCache,以追求極致效能。但如果頁面包含極度敏感的個人資料(如銀行餘額),仍應謹慎使用。

3. 未關閉的連接

如果頁面在隱藏前仍開著 WebSocketWebRTC 或連線中的 IndexedDB 事務,可能會導致 BFCache 失敗。

  • 建議做法: 在 pagehidevisibilitychange 發生時主動關閉這些連線。

4. 使用了 window.opener

如果頁面是透過 window.open 開啟且保留了對原頁面的引用,也可能影響快取。

最佳實踐建議

  1. 更新敏感資料: 既然頁面是從記憶體快照恢復的,上面的資料可能是數小時前的。務必在 pageshow 事件中重新整理時間、認證狀態或最新動態。
  2. 清理任務: 使用 pagehide 停止正在運行的動畫或不必要的計時器。
  3. 使用 DevTools 測試:
    • 打開 Chrome DevTools -> Application 選項卡。
    • 點擊左側的 Back/forward cache
    • 點擊 Test back/forward cache,它會自動測試並告訴你為什麼你的頁面無法進入快取。

透過優化 BFCache,你可以讓網站的導覽感受提升到另一個層次,減少等待時間並增加使用者留存率。

相關閱讀: