リソースをプリフェッチすると、ページの読み込み時間が短縮され、ビジネス指標が改善されます。
プリフェッチは、近い将来必要になると思われるリソース(またはページ全体)をダウンロードしてページの読み込みを高速化する手法です。調査によると、読み込み時間が短くなるほど、コンバージョン率が高くなり、ユーザー エクスペリエンスも向上することがわかっています。
Terra は、エンターテイメント、ニュース、スポーツを提供するブラジル最大級のコンテンツ ポータルで、月間 6,300 万人を超えるユニーク ユーザーがアクセスしています。Google は Terra のエンジニアリング チームと協力し、ウェブサイトの特定のセクションでプリフェッチ技術を使用することで、記事の読み込み時間を改善しました。
このケーススタディでは、Terra のジャーニーを実装した結果、モバイルでの広告クリック率(CTR)が 11% 向上、パソコンでの広告 CTR 30%、Largest Contentful Paint(LCP)回数の 50% 削減が実現しました。
プリフェッチ戦略
プリフェッチは以前から存在していますが、すぐには必要のないリソースのために余計な帯域幅を消費するため、慎重に使用することが重要です。この手法は、不要なデータ使用を避けるために慎重に適用する必要があります。Terra の場合、次の条件が満たされると、記事がプリフェッチされます。
- プリフェッチされた記事へのリンクの可視性: Terra は、Intersection Observer API を使用して、プリフェッチしたい記事を含むセクションの視認性を検出しました。
- データ使用量増加の好ましい条件: 前述したように、プリフェッチは、追加のデータを消費する投機的なパフォーマンスの改善であり、あらゆる状況で望ましい結果であるとは限りません。帯域幅が浪費される可能性を減らすため、Terra は Network Information API と Device Memory API を使用して、次の記事を取得するかどうかを判断します。Terra は、次の場合にのみ次の記事を取得します。
- 接続速度が 3G 以上で、デバイスに 4 GB 以上のメモリが搭載されている
- または iOS を搭載したデバイスの場合です。
- CPU がアイドル状態である: 最後に、Terra は
requestIdleCallback
を使用して、CPU がアイドル状態で追加の作業を実行できるかどうかをチェックします。メインスレッドがアイドル状態の場合、または特定の(オプションの)期限までに処理すべきコールバックを受け取ります。
これらの条件を遵守することで、Terra は必要な場合にのみデータを取得するようになり、帯域幅とバッテリー寿命を節約し、最終的に使用しないプリフェッチの影響を最小限に抑えることができます。
これらの条件が満たされると、Terra は、下の青色でハイライト表示されている [関連コンテンツ] セクションと [あなたへのおすすめ] セクションにある記事をプリフェッチします。
ビジネス上の効果
この手法の影響を測定するため、Terra はまず、記事ページの「関連コンテンツ」セクションでこの機能をリリースしました。UTM コードのおかげで、プリフェッチされた記事とプリフェッチされていない記事を区別して比較できるようになりました。2 週間にわたる A/B テストで成功を収めた Terra は、プリフェッチ機能を「あなたへのおすすめ」セクションに追加することにしました。
記事をプリフェッチした結果、広告指標が全体的に増加し、LCP と Time to First Byte(TTFB)の時間が短縮されました。
プリフェッチは慎重に使用すると、ページの読み込み時間が大幅に短縮され、広告指標が増加し、LCP 時間が短縮されます。
詳細な技術情報
プリフェッチを行うには、rel=prefetch
や rel=preload
などのリソースヒントを使用するか、quicklink や Guess.js などのライブラリを使用するか、新しい Speculation Rules 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
を使用して要素がビューポートに表示されるタイミングをモニタリングし、その後、プリフェッチ用のリストに URL を追加します。 - プリフェッチ プロセスは
requestIdleCallback
でスケジュールされ、メインスレッドがアイドル状態のときにprefetch
関数を実行することを目的としています。
おわりに
プリフェッチによって今後のナビゲーション リクエストの読み込み時間が大幅に短縮され、ユーザー ジャーニーの負担が軽減され、エンゲージメントが向上する可能性があります。プリフェッチによって、使用しない可能性のある余分なバイトが読み込まれるため、Terra は、適切なネットワーク条件下で、この情報が入手可能な対応デバイスでのみプリフェッチするという追加の措置を講じました。
この作業に協力してくれた Terra のエンジニアリング チームの Gilberto Cocchi、Harrey Theodoulou、Miguel Carlos Martínez Díaz、Barry Pollard、Jeremy Wagner、Leonardo Bellini、Lucca Paradeda に感謝します。