同期 XMLHttpRequest() でのページ終了の改善

遅延するナビを減らす

ジョー・メドレー
Joe Medley

ページまたはアプリを閉じたときに、送信されていないアナリティクスなどのデータが存在することはよくあります。一部のサイトでは、データの損失を防ぐために、XMLHttpRequest() の同期呼び出しを使用して、データがサーバーに渡されるまでページまたはアプリを開いたままにしています。より優れたデータの保存方法があるだけでなく、この手法では、ページを閉じるのが数秒ほど遅れて、ユーザー エクスペリエンスが低下します。

このやり方を変える必要があり、ブラウザが応答します。XMLHttpRequest() 仕様は、すでに非推奨と削除が予定されています。Chrome 80 ではまず、複数のイベント ハンドラ(具体的には beforeunloadunloadpagehidevisibilitychange)内で同期呼び出しが消去時に呼び出されたときに、同期呼び出しを禁止します。WebKit は最近、同じ動作変更を実装する commit も公開しました。

この記事では、サイトを更新する時間が必要なユーザー向けのオプションと、XMLHttpRequest() に代わる方法の概要を説明します。

一時的なオプトアウト

Chrome は単に XMLHttpRequest() からプラグを取り外そうとしているわけではありません。そのため、一時的なオプトアウト オプションがいくつか用意されています。インターネット上のサイトの場合、オリジン トライアルを利用できます。これにより、同期 XMLHttpRequest() 呼び出しを有効にするオリジン固有のトークンをページヘッダーに追加できます。このオプションは Chrome 89 リリースの少し前(2021 年 3 月頃)に終了します。Chrome Enterprise をご利用の場合は、同時に終了する AllowSyncXHRInPageDismissal ポリシーフラグを使用することもできます。

代替方法

サーバーにデータを返す方法に関係なく、すべてのデータを一度に送信する場合は、ページのアンロードを待たないことをおすすめします。最新のブラウザではアンロードは信頼性が低く、なんらかの問題が発生するとデータ損失のリスクもあります。ただし、ユーザー エクスペリエンスが低下することは別です。具体的には、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() はいずれかの時点でウェブ プラットフォームから削除される予定です。ブラウザベンダーは削除が必要であると同意していますが、これには時間がかかります。最悪のユースケースの一つを非推奨にすることは、すべてのユーザー エクスペリエンスを向上させるための第一歩です。

写真撮影: Matthew Hamilton(出典: Unsplash