Terra 如何運用預先擷取功能,將廣告點閱率提升 30%,並加速最大內容繪製速度。

預先擷取資源可加快網頁載入速度,並可改善業務指標。

Guilherme Moser de Souza
Guilherme Moser de Souza

預先擷取是一種技術,可透過下載資源,甚至是整個網頁來加快網頁載入速度,近期內可能需要用到這些資訊。研究顯示,縮短載入時間可以提高轉換率,並改善使用者體驗。

Terra 是巴西規模最大的內容入口網站之一,提供娛樂、新聞和運動賽事,每月吸引超過 6,300 萬名非重複訪客。我們與 Terra 的工程團隊合作,針對網站的特定區塊採用預先擷取技術,以縮短報導載入時間。

這份個案研究說明 Terra 如何成功將行動裝置上的廣告點閱率提升 11%、桌機上的廣告點閱率提高 30%,最大內容繪製 (LCP) 次數也減少了 50%。

預先擷取策略

預先擷取功能已使用一段時間,但請務必謹慎使用,因為它會將額外頻寬耗用給不需要立即使用的資源。請謹慎運用這項技巧,避免不必要的數據用量。針對 Terra,系統會在符合下列條件的情況下預先擷取報導:

  • 預先擷取報導連結的瀏覽權限:Trara 使用 Intersection Observer API 來偵測出要預先擷取報導的版面可視度。
  • 會增加數據用量的理想條件:如前所述,預先擷取是一種推測效能來改善效能,過程中會耗用額外資料,因此在各種情況下可能無法達到理想結果。為了降低浪費頻寬的可能性,Terra 會使用 Network Information APIDevice Memory API,來決定是否要擷取下一篇文章。Terra 只會在下列情況下擷取下一篇文章:
    • 連線速度至少為 3G,且裝置至少有 4 GB 的記憶體,
    • 還是 iOS 裝置
  • CPU 閒置:最後,Terra 會使用 requestIdleCallback 檢查 CPU 是否處於閒置狀態,並能執行額外工作。當主執行緒處於閒置狀態時,或在特定 (選用) 期限之前 (兩者取其先),系統就會處理回呼。

遵守這些條件,可確保 Terra 只在必要時才擷取資料,藉此節省頻寬和電池續航力,也能將無用的預先擷取作業影響降至最低。

符合這些條件時,Terra 會預先擷取以下版面中的報導:「相關內容」和「為您推薦」,並以藍色醒目顯示。

Terra 網站上兩個部分包含預先擷取連結的螢幕截圖。左側是醒目顯示「相關內容」部分,右側則是「為你推薦」部分。

業務影響

為了評估這個技巧的影響,Terra 先在文章頁面的「相關內容」部分推出這項功能。Urchin 流量監視器 (UTM) 程式碼有助於區分預先擷取和非預先擷取的文章,以便進行比較。經過兩週的 A/B 測試成功後,Terra 決定在「為您推薦」部分加入預先擷取功能。

預先擷取文章後,我們觀察到廣告指標整體提升,並縮短 LCP 和第一個位元組 (TTFB) 時間:

指標 行動裝置 電腦
廣告點閱率 +11% +30%
廣告可視度 +10.5% +6%
LCP 51% 73%
TTFB 83% 84%

預先擷取功能可大幅提升網頁載入時間、增加廣告指標,並縮短 LCP 時間。

技術詳細資料

如要預先擷取,可以使用 rel=prefetchrel=preload 等資源提示、QuicklinkGuess.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。