ユーザーがページやアプリを閉じたときに、未送信のアナリティクス データやその他のデータが残っていることはよくあります。データ損失を防ぐため、一部のサイトでは XMLHttpRequest() への同期呼び出しを使用して、データがサーバーに渡されるまでページまたはアプリを開いたままにします。データを保存するより良い方法があるだけでなく、この手法ではページのクローズが数秒遅れるため、ユーザー エクスペリエンスが低下します。
この慣行は変更される必要があり、ブラウザは対応しています。XMLHttpRequest() 仕様はすでに非推奨となり、削除される予定です。Chrome 80 では、いくつかのイベント ハンドラ(具体的には、破棄時に発火する beforeunload、unload、pagehide、visibilitychange)内での同期呼び出しを禁止することで、最初の一歩を踏み出します。WebKit でも最近、同じ動作変更を実装するコミットが追加されました。
サイトの更新に時間がかかるユーザー向けのオプションと、XMLHttpRequest() の代替手段の概要を簡単に説明します。
一時的なオプトアウト
Chrome は、デベロッパーが XMLHttpRequest() への依存を解消するための時間を提供したいと考えているため、一時的なオプトアウト オプションを提供しています。
オリジン トライアルに参加する。これにより、同期 XMLHttpRequest() 呼び出しを有効にするオリジン固有のトークンがページ ヘッダーに追加されます。このオプションは、Chrome 89 がリリースされる直前の 2021 年 3 月に終了します。Enterprise Chrome のお客様は、同じタイミングで終了する AllowSyncXHRInPageDismissal ポリシー フラグもご利用いただけます。
別の方法
サーバーにデータを返す方法に関係なく、ページがアンロードされるまで待ってからすべてのデータを一度に送信することは避けることをおすすめします。unload は、ユーザー エクスペリエンスを損なうだけでなく、最新のブラウザでは信頼性が低く、問題が発生した場合にデータ損失のリスクがあります。具体的には、モバイル オペレーティング システムでは unload イベントを発生させずにタブやブラウザを閉じる方法が多数あるため、アンロード イベントがモバイル ブラウザで発生しないことがよくあります。XMLHttpRequest() では、小さなペイロードを使用するかどうかを選択できました。現在は必須となっています。どちらの代替案も、仕様で定められているとおり、コンテキストごとに 64 KB のアップロード上限があります。
取得キープアライブ
Fetch API は、サーバーとのやり取りを処理する堅牢な手段と、さまざまなプラットフォーム API で使用できる一貫したインターフェースを提供します。オプションの 1 つである keepalive は、リクエストを行ったページが開いたままであるかどうかにかかわらず、リクエストが継続されるようにします。
window.addEventListener('unload', {
fetch('/siteAnalytics', {
method: 'POST',
body: getStatistics(),
keepalive: true
});
}
fetch() メソッドには、サーバーに送信される内容をより細かく制御できるという利点があります。この例では示していませんが、fetch() は Response オブジェクトで解決される Promise も返します。ページのアンロードを妨げないようにするため、何も処理しないことにしました。
SendBeacon()
SendBeacon() は、実際には内部で Fetch API を使用しています。そのため、ペイロードの 64 KB の制限が同じであり、ページがアンロードされた後もリクエストが継続されることが保証されます。主な利点は、そのシンプルさです。これにより、1 行のコードでデータを送信できます。
window.addEventListener('unload', {
navigator.sendBeacon('/siteAnalytics', getStatistics());
}
まとめ
ブラウザ全体で fetch() の利用が増加すれば、XMLHttpRequest() がウェブ プラットフォームから削除されることが期待されます。ブラウザ ベンダーは削除に同意していますが、時間がかかります。最悪のユースケースの 1 つを非推奨にすることは、すべてのユーザーのユーザー エクスペリエンスを向上させるための第一歩です。