リソースをプリフェッチすると、ページの読み込み時間が短縮され、ビジネス指標が改善されます。
プリフェッチは、近い将来必要となる可能性が高いリソース(またはページ全体)をダウンロードすることで、ページの読み込みを高速化する手法です。調査によると、読み込み時間が短くなるとコンバージョン率が向上し、ユーザー エクスペリエンスも向上します。
Terra はブラジル最大のコンテンツ ポータルの 1 つで、エンターテインメント、ニュース、スポーツを配信し、月間 6,300 万人以上のユニーク ビジターを抱えています。Google は Terra のエンジニアリング チームと連携し、ウェブサイトの特定のセクションでプリフェッチ手法を使用して、記事の読み込み時間を短縮しました。
このケーススタディでは、Terra がジャーニーを実装した結果、モバイルでの広告のクリック率(CTR)が 11% 増加し、デスクトップで 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 では、rel=prefetch
や Speculation Rules API などの他のプリフェッチ方法をまだサポートしていない Safari をサポートできるため、この選択を行いました。また、Terra のニーズでは、フル機能の JavaScript ライブラリは必要ありませんでした。
以下の 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 では、ネットワークの状態が良好で、この情報が利用可能な対応デバイスでのみプリフェッチを行うように特別な手順を追加しました。
この作業に協力してくれた Gilberto Cocchi、Harry Theodoulou、Miguel Carlos Martínez Díaz、Barry Pollard、Jeremy Wagner、Terra のエンジニアリング チームの Leonardo Bellini と Lucca Paradeda に感謝します。