ウェブページからサーバーにデータ(または「ビーコン」)を返す必要があるのは一般的です。たとえば、ユーザーの現在のセッションの分析データを例に考えてみましょう。デベロッパーにとっては、ビーコンが送信される前にタブが閉じられたり、ユーザーが移動したりしても、データが失われるリスクを負うことなく、絶え間ないリクエストを減らし、重複の可能性も抑えるというバランスを取る必要があります。
従来、デベロッパーは pagehide
イベントと visibilitychange
イベントを使用してページのアンロード時にキャッチし、navigator.sendBeacon()
または fetch()
を keepalive
とともに使用してデータをビーコン設定していました。ただし、どちらのイベントでも、ユーザーのブラウザによって異なる難しい特殊なケースがあり、特にモバイルでは、イベントがまったく届かないこともあります。
fetchLater()
は、この複雑さを 1 回の API 呼び出しに置き換える提案です。その名前が示すとおりの動作です。ページが閉じたりユーザーが移動したりしても、今後どこかの時点でリクエストが行われるようにブラウザに要求します。
fetchLater()
は、Chrome 121(2024 年 1 月リリース)から Chrome 126(2024 年 7 月)までのオリジン トライアルを利用している実際のユーザーを対象に、Chrome でお試しいただけます。
fetchLater()
API
const fetchLaterResult = fetchLater(request, options);
fetchLater()
は、一般的に fetch()
の引数と同じ、2 つの引数を取ります。
request
。文字列 URL またはRequest
インスタンスのいずれかです。- オプションの
options
オブジェクト。これは、activateAfter
というタイムアウトでfetch()
からoptions
を拡張します。
fetchLater()
は FetchLaterResult
を返します。現時点では、読み取り専用のプロパティ activated
のみが含まれています。このプロパティは、「後日」が渡されてフェッチが行われると true
に設定されます。fetchLater()
リクエストへのレスポンスはすべて破棄されます。
request
最も簡単な使用方法は、URL だけを使用する方法です。
fetchLater('/endpoint/');
ただし、fetch()
と同様に、fetchLater()
リクエストには、カスタム ヘッダー、認証情報の動作、POST
本文、キャンセルする可能性のある AbortController
signal
など、多くのオプションを設定できます。
fetchLater('/endpoint/', {
method: 'GET',
cache: 'no-store',
mode: 'same-origin',
headers: {Authorization: 'SUPER_SECRET'},
});
options
オプション オブジェクトは、タイムアウト(activateAfter
)の後、またはページがアンロードされたときに、どちらか早い方のタイミングでリクエストを発行したい場合は、fetch()
のオプションをタイムアウト付きで拡張します。
これにより、データの取得を可能な限り最後のタイミングで行うか、よりタイムリーに行うかのトレードオフを判断できます。
たとえば、ユーザーが普段営業日中ずっと開いたままにしているアプリがある場合、1 時間のタイムアウトを設定して、より詳細な分析ができるようにしつつ、ユーザーがその時間より前にアプリを終了した場合、ビーコンを保証できます。その後、新しい fetchLater()
を設定して、今後 1 時間の分析を行うことができます。
const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});
使用例:
実際にサイトで Core Web Vitals を測定する場合の問題の 1 つは、ユーザーが実際にページを離れるまでのパフォーマンス指標がどれも変化する可能性があることです。たとえば、いつでも大きなレイアウト シフトが発生する可能性があり、ページでインタラクションへの応答に時間がかかる可能性があります。
ただし、ページのアンロード時にビーコンのバグや不完全性が原因で、すべてのパフォーマンス データが失われないようにする必要があります。fetchLater()
にとって最適な候補者です。
この例では、web-vitals.js ライブラリを使用して指標をモニタリングし、fetchLater()
を使用して結果を分析エンドポイントに報告しています。
import {onCLS, onINP, onLCP} from 'web-vitals';
const queue = new Set();
let fetchLaterController;
let fetchLaterResult;
function updateQueue(metricUpdate) {
// If there was an already complete request for whatever
// reason, clear out the queue of already-sent updates.
if (fetchLaterResult?.activated) {
queue.clear();
}
queue.add(metricUpdate);
// JSON.stringify used here for simplicity and will likely include
// more data than you need. Replace with a preferred serialization.
const body = JSON.stringify([...queue]);
// Abort any existing `fetchLater()` and schedule a new one with
// the update included.
fetchLaterController?.abort();
fetchLaterController = new AbortController();
fetchLaterResult = fetchLater('/analytics', {
method: 'POST',
body,
signal: fetchLaterController.signal,
activateAfter: 60 * 60 * 1000, // Timeout to ensure timeliness.
});
}
onCLS(updateQueue);
onINP(updateQueue);
onLCP(updateQueue);
指標が更新されるたびに、スケジュール設定されている既存の fetchLater()
は AbortController
でキャンセルされ、更新を含む新しい fetchLater()
が作成されます。
fetchLater()
を試す
記載のとおり、fetchLater()
は Chrome 126 までオリジン トライアルでご利用いただけます。オリジン トライアルの背景情報については、オリジン トライアルを使ってみるをご覧ください。
ローカルテストでは、chrome://flags/#enable-experimental-web-platform-features
にある試験運用版ウェブ プラットフォームの機能フラグで fetchLater
を有効にできます。これは、--enable-experimental-web-platform-features
を使用してコマンドラインから Chrome を実行するか、より対象を絞った --enable-features=FetchLaterAPI
フラグを使用して有効にすることもできます。
公開ページでこの機能を使用する場合は、使用する前にグローバル fetchLater
が定義されているかどうかをチェックして、機能検出を行ってください。
if (globalThis.fetchLater) {
// Set up beaconing using fetchLater().
// ...
}
フィードバック
新しいウェブ API を正しく使用するには、デベロッパーからのフィードバックが不可欠です。GitHub で問題やフィードバックを報告してください。