Phase d'évaluation de l'API fetchLater

Brendan Kenny
Brendan Kenny

Il est courant que les pages Web aient besoin de renvoyer des données (ou "balise ") à leur serveur (par exemple, les données d'analyse relatives à la session en cours d'un utilisateur). Pour les développeurs, cela implique de trouver un équilibre: réduire les demandes constantes, voire redondantes, sans risquer de manquer de données si l'onglet était fermé ou si l'utilisateur a quitté la page avant qu'une balise puisse être envoyée.

Traditionnellement, les développeurs utilisaient les événements pagehide et visibilitychange pour intercepter la page lors de son déchargement, puis utiliser navigator.sendBeacon() ou fetch() avec keepalive pour baliser les données. Cependant, ces deux événements présentent des cas difficiles qui diffèrent selon le navigateur de l'utilisateur. Parfois, ils n'arrivent jamais du tout, en particulier sur un appareil mobile.

fetchLater() est une proposition visant à remplacer cette complexité par un seul appel d'API. Comme son nom l'indique, elle demande au navigateur de s'assurer qu'une requête sera effectuée à un moment donné, même si la page est fermée ou si l'utilisateur quitte la page.

fetchLater() est disponible dans Chrome pour être testé par de vrais utilisateurs après une phase d'évaluation à partir de la version 121 (publiée en janvier 2024) et jusqu'à Chrome 126 (juillet 2024).

L'API fetchLater()

const fetchLaterResult = fetchLater(request, options);

fetchLater() comporte deux arguments, généralement identiques à ceux de fetch():

  • Le request correspond à une URL de chaîne ou à une instance Request.
  • Un objet options facultatif, qui étend le options à partir de fetch() avec un délai avant expiration appelé activateAfter.

fetchLater() renvoie un FetchLaterResult, qui ne contient actuellement qu'une seule propriété en lecture seule activated, qui sera définie sur true une fois que la requête aura été effectuée et que la récupération aura été effectuée. Toutes les réponses à la requête fetchLater() sont supprimées.

request

La méthode la plus simple consiste à utiliser une URL seule:

fetchLater('/endpoint/');

Toutefois, tout comme fetch(), un grand nombre d'options peuvent être définies sur une requête fetchLater(), y compris des en-têtes personnalisés, le comportement des identifiants, un corps POST et un AbortController signal pour éventuellement l'annuler.

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

options

L'objet d'options étend les options de fetch() avec un délai d'inactivité, activateAfter, au cas où vous souhaiteriez déclencher la requête après le délai ou lorsque la page est déchargée, selon la première échéance atteinte.

Cela vous permet de décider du compromis entre l'obtention de données au tout dernier moment possible ou lorsqu'elles sont plus opportunes.

Par exemple, si l'une de vos applications reste ouverte toute la journée de travail, vous pouvez définir un délai d'inactivité d'une heure afin d'obtenir des données analytiques plus précises tout en garantissant une balise si l'utilisateur a quitté l'application à tout moment avant la fin de l'heure. Un nouveau fetchLater() peut ensuite être configuré pour la prochaine heure d'analyse.

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

Exemple d'utilisation

Lorsque vous mesurez les Core Web Vitals sur le terrain, l'un des problèmes est que toutes les métriques de performances peuvent changer jusqu'à ce que l'utilisateur quitte la page. Par exemple, des décalages de mise en page plus importants peuvent se produire à tout moment, ou la page peut mettre encore plus de temps à répondre à une interaction.

Toutefois, vous ne devez pas risquer de perdre toutes les données de performances à cause de bugs ou de balises incomplètes lors du déchargement de la page. C'est un candidat idéal pour fetchLater().

Dans cet exemple, la bibliothèque web-vitals.js permet de surveiller les métriques, tandis que fetchLater() permet de transmettre les résultats à un point de terminaison d'analyse:

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

Chaque fois qu'une mise à jour des métriques est disponible, toute fetchLater() planifiée existante est annulée avec un AbortController et un fetchLater() est créé avec la mise à jour incluse.

Essayer fetchLater()

Comme indiqué, fetchLater() est disponible en phase d'évaluation jusqu'à Chrome 126. Consultez Premiers pas avec les phases d'évaluation pour obtenir des informations générales sur ces phases.

Pour effectuer des tests en local, fetchLater peut être activé à l'aide de l'indicateur de fonctionnalités expérimentales de la plate-forme Web sur chrome://flags/#enable-experimental-web-platform-features. Vous pouvez également l'activer en exécutant Chrome à partir de la ligne de commande avec --enable-experimental-web-platform-features ou l'indicateur --enable-features=FetchLaterAPI, plus ciblé.

Si vous l'utilisez sur une page publique, assurez-vous de détecter les fonctionnalités en vérifiant si la fetchLater globale est définie avant de l'utiliser:

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

Commentaires

Les commentaires des développeurs sont essentiels pour réussir le lancement des nouvelles API Web. N'hésitez donc pas à signaler des problèmes et des commentaires sur GitHub.

En savoir plus