往返快取 notRestoredReasons API

找出哪些導覽遭封鎖而無法使用 bfcache,以及原因。

加入 PerformanceNavigationTiming 類別的 notRestoredReasons 屬性會回報資訊,說明文件中的影格是否因導覽而無法使用 bfcache,以及原因。開發人員可以運用這項資訊找出需要更新的網頁,使其與 bfcache 相容,進而提升網站效能。

目前狀態

notRestoredReasons API 已在 Chrome 123 中發布,並逐步推出。

概念和用途

新式瀏覽器提供名為「往返快取」(bfcache) 的最佳化功能,可提升瀏覽記錄的導覽體驗。這樣一來,使用者返回先前造訪過的網頁時,就能立即載入網頁。網頁可能因各種原因無法進入 bfcache,或在 bfcache 中遭到逐出,有些原因符合規格要求,有些則與瀏覽器實作方式有關。

先前,開發人員無法得知網頁在實際環境中無法使用 bfcache 的原因,但 Chrome 開發人員工具中提供測試。如要在欄位中啟用監控功能,請擴充 PerformanceNavigationTiming 類別,加入 notRestoredReasons 屬性。這會傳回一個物件,其中包含頂端影格和文件中所有 iframe 的相關資訊:

  • 他們無法使用 bfcache 的原因。
  • 例如影格 idname,有助於找出 HTML 中的 iframe。

    開發人員可據此採取行動,讓這些網頁與 bfcache 相容,進而提升網站效能。

範例

您可以透過 Performance.getEntriesByType()PerformanceObserver 等功能取得 PerformanceNavigationTiming 執行個體。

舉例來說,您可以叫用下列函式,傳回效能時間軸中的所有 PerformanceNavigationTiming 物件,並記錄其 notRestoredReasons

function returnNRR() {
  const navEntries = performance.getEntriesByType("navigation");
  for (let i = 0; i < navEntries.length; i++) {
    console.log(`Navigation entry ${i}`);
    let navEntry = navEntries[i];
    console.log(navEntry.notRestoredReasons);
  }
}

如果是歷來導覽,PerformanceNavigationTiming.notRestoredReasons 屬性會傳回具有下列結構的物件,代表頂層影格的封鎖狀態:

{
  children: [],
  id: null,
  name: null,
  reasons: [
    {"reason", "unload-listener"}
  ],
  src: null,
  url: "https://www.example.com/page/"
}

屬性如下:

children
物件陣列,代表嵌入頂層框架的任何同源框架的封鎖狀態。每個物件的結構都與父項物件相同,因此物件內可遞迴表示任意層級的內嵌影格。如果影格沒有子項,陣列會是空白。
id
:代表影格 id 屬性值的字串 (例如 <iframe id="foo" src="...">)。如果影格沒有 id,值會是 null。頂層頁面為 null
name
代表影格 name 屬性值的字串 (例如 <iframe name="bar" src="...">)。如果影格沒有 name,值會是空字串。頂層頁面為 null
reasons
字串陣列,每個字串都代表導覽網頁遭封鎖而無法使用 bfcache 的原因。封鎖的原因有很多,詳情請參閱「封鎖原因」一節。
src
代表影格來源路徑的字串 (例如 <iframe src="b.html">)。如果影格沒有 src,值會是空字串。頂層頁面為 null
url
代表導覽頁面/iframe 網址的字串。

如果 PerformanceNavigationTiming 物件不代表歷來導覽,notRestoredReasons 屬性會傳回 null

請注意,如果沒有任何封鎖原因,notRestoredReasons 也會傳回 null,因此 null 並不代表系統是否使用 bfcache。為此,你必須使用 event.persisted 屬性

回報同源框架中封鎖 bfcache 的情況

如果網頁內嵌了同源框架,傳回的 notRestoredReasons 值會包含 children 屬性內的物件,代表每個內嵌框架的封鎖狀態。

例如:

{
  children: [
    {
      children: [],
      id: "iframe-id",
      name: "iframe-name",
      reasons: [],
      src: "./index.html",
      url: "https://www.example.com/"
    },
    {
      children: [],
      id: "iframe-id2",
      name: "iframe-name2",
      reasons: [
        {"reason": "unload-listener"}
      ],
      src: "./unload-examples.html",
      url: "https://www.example.com/unload-examples.html"
    },
  ],
  id: null,
  name: null,
  reasons: [],
  src: null,
  url:"https://www.example.com"
}

回報跨原始來源框架中封鎖 bfcache 的情況

如果網頁內嵌跨來源框架,我們會限制分享的相關資訊量,避免跨來源資訊外洩。我們只會納入外部網頁已知的資訊,以及跨來源子樹狀結構是否封鎖 bfcache。我們不會納入任何封鎖原因,也不會提供子樹狀結構較低層級的相關資訊 (即使部分子層級屬於同源)。

例如:

{
  children: [
    {
      children: [],
      id: "iframe-id",
      name: "iframe-name",
      reasons: [],
      src: "./index.html",
      url: "https://www.example2.com/"
    }
  ],
  id: null,
  name: null,
  reasons: [
        {"reason": "masked"}
  ],
  src: null,
  url:"https://www.example.com"
}

對於所有跨來源 iframe,我們會回報影格的 reasonsnull,而頂層影格會顯示 "masked" 原因。請注意,"masked" 也可能因使用者代理程式專屬原因而使用,因此不一定表示 iframe 中有問題。

如要進一步瞭解安全性和隱私權注意事項,請參閱說明文章中的「安全性和隱私權」一節。

封鎖原因

如先前所述,封鎖的原因有很多:

以下列舉幾個最常見的 bfcache 無法使用原因:

  • unload-listener:網頁會註冊 unload 處理常式,導致特定瀏覽器無法使用往返快取。詳情請參閱「淘汰卸載事件」。
  • response-cache-control-no-store:網頁使用 no-store 做為 cache-control 值。
  • related-active-contents:網頁是從其他網頁開啟 (使用「複製分頁」),且其他網頁仍參照這個網頁。

意見回饋

Chromium 團隊想瞭解您使用 bfcache notRestoredReasons API 的體驗。

介紹 API 設計

API 是否有任何不符合預期的地方?或者,是否有缺少的屬性或方法,導致您無法實作想法?對安全模型有任何問題或意見嗎?在對應的 GitHub 存放區中提出規格問題,或在現有問題中新增想法。

回報導入問題

您是否發現 Chromium 實作有錯誤?還是實作方式與規格不同? 在問題追蹤工具中回報錯誤。請務必盡可能提供詳細資料、重現問題的簡單操作說明,並指定元件為 UI > Browser > Navigation > BFCache

支援 API

您打算使用 bfcache notRestoredReasons API 嗎?您的公開支持有助於 Chromium 團隊優先處理功能,並向其他瀏覽器供應商展現支援這些功能的重要性。

使用主題標記 #NotRestoredReasons 傳送推文給 @ChromiumDev,告訴我們您在何處使用這項功能,以及使用方式。

實用連結