Ursprungstest der AbrufLater API

Brendan Kenny
Brendan Kenny

Es ist üblich, dass Webseiten Daten (oder „Beacons“) an ihren Server zurücksenden müssen. Denken Sie beispielsweise an Analysedaten für die aktuelle Sitzung eines Nutzers. Für Entwickler ist das ein Balanceakt: ständige, möglicherweise redundante Anfragen reduzieren, ohne das Risiko einzugehen, dass Daten verloren gehen, wenn der Tab geschlossen wurde oder der Nutzer wegnavigiert, bevor ein Beacon gesendet werden kann.

Bisher haben Entwickler pagehide- und visibilitychange-Ereignisse verwendet, um die Seite beim Entladen zu erfassen. Anschließend haben sie navigator.sendBeacon() oder fetch() mit keepalive verwendet, um ein Beacon für Daten zu erstellen. Bei beiden Ereignissen gibt es jedoch schwierige Sonderfälle, die sich je nach Browser des Nutzers unterscheiden. Manchmal werden die Ereignisse gar nicht gesendet, insbesondere auf Mobilgeräten.

fetchLater() ist ein Vorschlag, diese Komplexität durch einen einzigen API-Aufruf zu ersetzen. Sie funktioniert genau wie der Name vermuten lässt: Der Browser wird aufgefordert, dafür zu sorgen, dass eine Anfrage zu einem bestimmten Zeitpunkt in der Zukunft gestellt wird, auch wenn die Seite geschlossen oder der Nutzer wegklickt.

fetchLater() ist in Chrome ab Version 121 (veröffentlicht im Januar 2024) für Tests mit echten Nutzern im Rahmen eines Ursprungstests verfügbar. Dieser läuft bis zum 3. September 2024.

Mit der fetchLater() API

const fetchLaterResult = fetchLater(request, options);

fetchLater() nimmt zwei Argumente an, die in der Regel mit denen von fetch() identisch sind:

  • Die request, entweder eine String-URL oder eine Request-Instanz.
  • Ein optionales options-Objekt, das die options von fetch() mit einem Zeitlimit namens activateAfter verlängert.

fetchLater() gibt eine FetchLaterResult zurück, die derzeit nur eine einzige schreibgeschützte Eigenschaft activated enthält. Sie wird auf true gesetzt, wenn "später" vergangen ist und der Abruf erfolgt ist. Alle Antworten auf die fetchLater()-Anfrage werden verworfen.

request

Die einfachste Verwendung ist eine URL allein:

fetchLater('/endpoint/');

Aber genau wie fetch() kann für eine fetchLater()-Anfrage eine große Anzahl von Optionen festgelegt werden, darunter benutzerdefinierte Header, Verhalten von Anmeldedaten, ein POST-Text und ein AbortController-signal zum potenziell Abbrechen.

fetchLater('/endpoint/', {
  method: 'GET',
  cache: 'no-store',
  mode: 'same-origin',
  headers: {Authorization: 'SUPER_SECRET'},
});

options

Das Optionsobjekt erweitert die Optionen von fetch() um ein Zeitlimit, activateAfter, falls die Anfrage nach dem Zeitlimit oder beim Entladen der Seite ausgelöst werden soll, je nachdem, was zuerst eintritt.

So können Sie entscheiden, ob Sie Daten so spät wie möglich oder zu einem späteren Zeitpunkt erhalten möchten.

Wenn Nutzer Ihre App beispielsweise normalerweise den ganzen Arbeitstag lang geöffnet lassen, sollten Sie eine Zeitüberschreitung von einer Stunde festlegen, um detailliertere Analysen zu erhalten. Gleichzeitig wird aber sichergestellt, dass ein Beacon gesendet wird, wenn der Nutzer die App vor Ablauf dieser Stunde schließt. Für die nächste Stunde mit Analysen kann dann eine neue fetchLater() eingerichtet werden.

const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});

Anwendungsbeispiel

Ein Problem bei der Messung der Core Web Vitals im Feld besteht darin, dass sich die Leistungsmesswerte ändern können, bis der Nutzer eine Seite tatsächlich verlässt. So können beispielsweise jederzeit größere Layout-Shifts auftreten oder die Seite reagiert noch länger auf eine Interaktion.

Sie möchten jedoch vermeiden, dass beim Entladen der Seite alle Leistungsdaten aufgrund von fehlerhaften oder unvollständigen Beaconing-Daten verloren gehen. Sie ist der perfekte Kandidat für fetchLater().

In diesem Beispiel wird die web-vitals.js-Bibliothek verwendet, um die Messwerte zu überwachen, und fetchLater(), um die Ergebnisse an einen Analyseendpunkt zu senden:

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);

Bei jeder Aktualisierung eines Messwerts werden vorhandene geplante fetchLater()-Elemente mit einem AbortController abgebrochen und eine neue fetchLater() mit der Aktualisierung erstellt.

fetchLater() jetzt verwenden

Wie bereits erwähnt, ist fetchLater() bis Chrome 126 in einem Ursprungstest verfügbar. Einstieg in Herkunftstests

Für lokale Tests kann fetchLater mit dem Flag „Experimental Web Platform features“ (Experimentelle Webplattform-Funktionen) unter chrome://flags/#enable-experimental-web-platform-features aktiviert werden. Sie können sie auch aktivieren, indem Sie Chrome über die Befehlszeile mit --enable-experimental-web-platform-features oder dem gezielteren Flag --enable-features=FetchLaterAPI ausführen.

Wenn du die Funktion auf einer öffentlichen Seite verwendest, solltest du die Funktion erkennen lassen, indem du prüfst, ob die globale fetchLater definiert ist, bevor du sie verwendest:

if (globalThis.fetchLater) {
  // Set up beaconing using fetchLater().
  // ...
}

Feedback

Entwicklerfeedback ist für die Entwicklung neuer Web-APIs von entscheidender Bedeutung. Bitte melden Sie Probleme und Feedback auf GitHub.

Weitere Informationen