預先擷取資源可加快網頁載入速度,並可改善業務指標。
預先擷取是一種技術,可透過下載資源,甚至是整個網頁來加快網頁載入速度,近期內可能需要用到這些資訊。研究顯示,縮短載入時間可以提高轉換率,並改善使用者體驗。
Terra 是巴西規模最大的內容入口網站之一,提供娛樂、新聞和運動賽事,每月吸引超過 6,300 萬名非重複訪客。我們與 Terra 的工程團隊合作,針對網站的特定區塊採用預先擷取技術,以縮短報導載入時間。
這份個案研究說明 Terra 如何成功將行動裝置上的廣告點閱率提升 11%、桌機上的廣告點閱率提高 30%,最大內容繪製 (LCP) 次數也減少了 50%。
預先擷取策略
預先擷取功能已使用一段時間,但請務必謹慎使用,因為它會將額外頻寬耗用給不需要立即使用的資源。請謹慎運用這項技巧,避免不必要的數據用量。針對 Terra,系統會在符合下列條件的情況下預先擷取報導:
- 預先擷取報導連結的瀏覽權限:Trara 使用 Intersection Observer API 來偵測出要預先擷取報導的版面可視度。
- 會增加數據用量的理想條件:如前所述,預先擷取是一種推測效能來改善效能,過程中會耗用額外資料,因此在各種情況下可能無法達到理想結果。為了降低浪費頻寬的可能性,Terra 會使用 Network Information API 和 Device Memory API,來決定是否要擷取下一篇文章。Terra 只會在下列情況下擷取下一篇文章:
- 連線速度至少為 3G,且裝置至少有 4 GB 的記憶體,
- 還是 iOS 裝置
- CPU 閒置:最後,Terra 會使用
requestIdleCallback
檢查 CPU 是否處於閒置狀態,並能執行額外工作。當主執行緒處於閒置狀態時,或在特定 (選用) 期限之前 (兩者取其先),系統就會處理回呼。
遵守這些條件,可確保 Terra 只在必要時才擷取資料,藉此節省頻寬和電池續航力,也能將無用的預先擷取作業影響降至最低。
符合這些條件時,Terra 會預先擷取以下版面中的報導:「相關內容」和「為您推薦」,並以藍色醒目顯示。
業務影響
為了評估這個技巧的影響,Terra 先在文章頁面的「相關內容」部分推出這項功能。Urchin 流量監視器 (UTM) 程式碼有助於區分預先擷取和非預先擷取的文章,以便進行比較。經過兩週的 A/B 測試成功後,Terra 決定在「為您推薦」部分加入預先擷取功能。
預先擷取文章後,我們觀察到廣告指標整體提升,並縮短 LCP 和第一個位元組 (TTFB) 時間:
預先擷取功能可大幅提升網頁載入時間、增加廣告指標,並縮短 LCP 時間。
技術詳細資料
如要預先擷取,可以使用 rel=prefetch
或 rel=preload
等資源提示、Quicklink 或 Guess.js 等程式庫,或是新版的推測規則 API。Terra 選擇實作時會使用 fetch API 搭配低優先順序,再搭配 Intersection Observer 執行個體。Terra 因此能支援 Safari,因為 Safari 尚未支援其他預先擷取方法 (例如 rel=prefetch
或 Speculation Rules API),而且他不需要功能完整的 JavaScript 程式庫,就能滿足 Terra 的需求。
以下 JavaScript 與 Terra 使用的程式碼大致相同:
function prefetch(nodeLists) {
// Exclude slow ECTs < 3g
if (navigator.connection &&
(navigator.connection.effectiveType === 'slow-2g'
|| navigator.connection.effectiveType === '2g')
) {
return;
}
// Exclude low end device which is device with memory <= 2GB
if (navigator.deviceMemory && navigator.deviceMemory <= 2) {
return;
}
const fetchLinkList = {};
const observer = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
if (!fetchLinkList[entry.target.href]) {
fetchLinkList[entry.target.href] = true;
fetch(entry.target, {
priority: 'low'
});
}
observer.unobserve(entry = entry.target);
}
});
});
}
const idleCallback = window.requestIdleCallback || function (cb) {
let start = Date.now();
return setTimeout(function () {
cb({
didTimeout: false,
timeRemaining: function () {
return Math.max(0, 50 - (Date.now() - start));
}
});
}, 1);
}
idleCallback(function () {
prefetch(nodeLists)
})
prefetch
函式會先檢查連線品質和裝置記憶體的最低連線需求,再啟動預先擷取作業。- 然後,系統會使用
IntersectionObserver
來監控元素在可視區域中可見的時機,隨後就會將網址加入清單,以便預先擷取。 - 預先擷取程序是以
requestIdleCallback
排定,目的是在主執行緒處於閒置狀態時執行prefetch
函式。
結論
請謹慎使用預先擷取功能,可以大幅縮短之後進行導航時的載入時間,進而減少使用者歷程的流暢度並提高參與度。預先擷取會導致系統載入可能會用到的額外位元組,因此 Terra 只針對網路狀況良好的網路狀況,以及在支援 (具有這項資訊的裝置) 的情況下才預先擷取,也採取額外步驟。
特別感謝 Terra 工程團隊的 Gilberto Cocchi、Harry Theodoulou、Miguel Carlos Martínez Díaz、Barry Pollard、Jeremy Wagner,以及 Terra 工程團隊 Leonardo Bellini 和 Lucca Paradeda。