使用者關閉網頁或應用程式時,網頁或應用程式通常會有未提交的 Analytics 或其他資料。為避免資料遺失,部分網站會使用同步呼叫,XMLHttpRequest()讓網頁或應用程式保持開啟狀態,直到資料傳遞至伺服器為止。不僅有更好的資料儲存方式,這種技術還會延遲網頁關閉時間,最長可達數秒,造成不良的使用者體驗。
這種做法必須改變,瀏覽器也正在做出回應。XMLHttpRequest()規格已預定淘汰並移除。Chrome 80 會禁止在幾個事件處理常式 (具體來說,是在關閉時觸發的 beforeunload、unload、pagehide 和 visibilitychange) 內進行同步呼叫,這是第一步。WebKit 最近也提交了實作相同行為變更的內容。
我會簡要說明相關選項,供需要時間更新網站的商家參考,並列出 XMLHttpRequest() 的替代方案。
暫時選擇退出
Chrome 希望提供開發人員時間,移除對 XMLHttpRequest() 的依賴,因此我們提供暫時停用選項。
加入來源試用計畫。這樣一來,您就能在網頁標頭中加入來源專屬權杖,啟用同步 XMLHttpRequest()呼叫。這項選項將在 Chrome 89 版發布前不久終止,預計於 2021 年 3 月推出。企業版 Chrome 客戶也可以使用 AllowSyncXHRInPageDismissal 政策旗標,該旗標也會在同一時間終止。
替代方案
無論您如何將資料傳回伺服器,最好都不要等到網頁卸載時才一次傳送所有資料。除了會造成不良的使用者體驗外,在現代瀏覽器上,卸載功能不可靠,如果發生錯誤,還可能導致資料遺失。具體來說,由於行動作業系統提供多種關閉分頁或瀏覽器的方式,因此卸載事件通常不會在行動瀏覽器上觸發,也不會觸發 unload 事件。在 XMLHttpRequest() 中,使用小型酬載是選項之一。現在這是必要條件。根據規格規定,這兩種替代方案的每個內容上傳限制都是 64 KB。
擷取保持運作
Fetch API 提供強大的方式來處理伺服器互動,並提供一致的介面,可在不同平台 API 中使用。其中一個選項是 keepalive,可確保要求持續進行,無論發出要求的網頁是否保持開啟:
window.addEventListener('unload', {
fetch('/siteAnalytics', {
method: 'POST',
body: getStatistics(),
keepalive: true
});
}
fetch() 方法的優點是可進一步控管傳送至伺服器的內容。範例中未顯示的是,fetch() 也會傳回承諾,並以 Response 物件解析。由於我嘗試避免網頁卸載,因此選擇不對其執行任何操作。
SendBeacon()
SendBeacon() 實際上會在幕後使用 Fetch API,因此具有相同的 64 KB 酬載限制,且也會確保要求在網頁卸載後繼續傳送。主要優點是簡單易用。您只要使用一行程式碼,就能提交資料:
window.addEventListener('unload', {
navigator.sendBeacon('/siteAnalytics', getStatistics());
}
結論
隨著瀏覽器fetch()的可用性提高,XMLHttpRequest() 有望從網頁平台中移除。瀏覽器供應商同意應移除這項功能,但需要時間。淘汰其中一個最糟糕的用途,是改善所有使用者體驗的第一步。