RetrieLater API 來源試用

Brendan Kenny
Brendan Kenny

網頁通常需要將資料 (或「信標」) 傳回伺服器,例如使用者目前工作階段的數據。對開發人員而言,這樣的情況需要平衡:減少持續性、可能重複,且在分頁關閉或使用者在信標傳送前離開時,都不會有遺漏資料的風險。

傳統上,開發人員會使用 pagehidevisibilitychange 事件,在頁面卸載時擷取頁面,然後使用 navigator.sendBeacon()fetch() 搭配 keepalive 傳送信標資料。不過,這兩種事件都存在難以處理的特殊情況,而且情況會因使用者的瀏覽器而異,有時事件可能完全不會傳送,尤其是在行動裝置上。

fetchLater() 是一種提案,可用單一 API 呼叫取代這項複雜作業。這項功能的運作方式正如其名稱所示:它會要求瀏覽器在未來某個時間點提出要求,即使網頁已關閉或使用者離開網頁,也一樣。

fetchLater() 可在 Chrome 中使用,讓您透過來源試用版測試真實使用者,這項測試將從 121 版 (2024 年 1 月發布) 開始,並持續到 2024 年 9 月 3 日。

fetchLater() API

const fetchLaterResult = fetchLater(request, options);

fetchLater() 會使用兩個引數,通常與 fetch() 的引數相同:

  • request,可以是字串網址或 Request 例項。
  • 選用的 options 物件,可透過名為 activateAfter 的逾時時間,從 fetch() 延伸 options

fetchLater() 會傳回 FetchLaterResult,目前只包含單一唯讀屬性 activated,如果傳遞「稍後」且系統執行擷取作業,這個屬性會設為 true。系統會捨棄對 fetchLater() 要求的任何回應。

request

最簡單的用法就是單獨使用網址:

fetchLater('/endpoint/');

不過,就像 fetch() 一樣,您可以在 fetchLater() 要求中設定大量選項,包括自訂標頭、憑證行為、POST 主體,以及可能會取消 AbortController signal 的選項

fetchLater('/endpoint/', {
  method: 'GET',
  cache: 'no-store',
  mode: 'same-origin',
  headers: {Authorization: 'SUPER_SECRET'},
});

options

選項物件會使用逾時時間 activateAfter 擴充 fetch() 的選項,以便在逾時或網頁卸載時 (以先到者為準) 觸發要求。

這樣一來,您就能決定要以最晚的時間取得資料,還是以更即時的方式取得資料。

舉例來說,如果您的使用者經常在工作日內使用某個應用程式,建議您設定一個小時的逾時值,以便確保更精細的分析結果,同時確保使用者在該小時結束前隨時離開時,能取得信標。接著,您可以為下一個小時的數據分析設定新的 fetchLater()

const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});

使用範例

在實地測量Core Web Vitals 時,會遇到一個問題,就是在使用者實際離開網頁之前,任何效能指標都可能會改變。舉例來說,版面配置位移可能隨時發生,或是頁面回應互動所需的時間更長。

不過,您不希望因網頁卸載時發生錯誤或信標傳送不完整,而導致所有成效資料都遺失。這是fetchLater()的理想候選人。

在此範例中,web-vitals.js 程式庫用於監控指標,而 fetchLater() 則用於將結果回報給分析端點:

import {onCLS, onINP, onLCP} from 'web-vitals';

const queue = new Set();
let fetchLaterController;
let fetchLaterResult;

function updateQueue(metricUpdate) {
  // If there was an already complete request for whatever
  // reason, clear out the queue of already-sent updates.
  if (fetchLaterResult?.activated) {
    queue.clear();
  }

  queue.add(metricUpdate);

  // JSON.stringify used here for simplicity and will likely include
  // more data than you need. Replace with a preferred serialization.
  const body = JSON.stringify([...queue]);

  // Abort any existing `fetchLater()` and schedule a new one with
  // the update included.
  fetchLaterController?.abort();
  fetchLaterController = new AbortController();
  fetchLaterResult = fetchLater('/analytics', {
    method: 'POST',
    body,
    signal: fetchLaterController.signal,
    activateAfter: 60 * 60 * 1000, // Timeout to ensure timeliness.
  });
}

onCLS(updateQueue);
onINP(updateQueue);
onLCP(updateQueue);

每當指標更新時,系統會使用 AbortController 取消任何現有的排程 fetchLater(),並建立新的 fetchLater(),其中包含更新資訊。

試用「fetchLater()

如前所述,fetchLater() 在 Chrome 126 之前會提供來源試用。如要瞭解來源試用的背景資訊,請參閱「開始進行來源試用

如要進行本機測試,您可以使用 chrome://flags/#enable-experimental-web-platform-features 中的實驗性 Web 平台功能旗標啟用 fetchLater。您也可以透過指令列執行 Chrome,並使用 --enable-experimental-web-platform-features 或更精準的 --enable-features=FetchLaterAPI 旗標啟用此功能。

如果您在公開頁面上使用這項功能,請務必先確認是否已定義全域 fetchLater,再使用這項功能:

if (globalThis.fetchLater) {
  // Set up beaconing using fetchLater().
  // ...
}

意見回饋

開發人員的意見回饋對於新網路 API 的正確性至關重要,因此請在 GitHub 回報問題和意見回饋

更多資訊