Il est courant que les pages Web doivent renvoyer des données (ou "balises ") à leur serveur. Par exemple, il peut s'agir de données analytiques pour la session en cours d'un utilisateur. Pour les développeurs, cela nécessite un équilibre: réduire les requêtes constantes, éventuellement redondantes, sans risquer de manquer de données si l'onglet a été 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 capturer la page lors de son déchargement, puis navigator.sendBeacon()
ou un fetch()
avec keepalive
pour diffuser des données. Cependant, ces deux événements présentent des cas difficiles qui diffèrent selon le navigateur de l'utilisateur. Parfois, les événements n'arrivent même pas, en particulier sur mobile.
fetchLater()
est une proposition visant à remplacer cette complexité par un seul appel d'API. Elle fait exactement ce que son nom suggère : elle demande au navigateur de s'assurer qu'une requête sera envoyée à un moment donné, même si la page est fermée ou que l'utilisateur quitte la page.
fetchLater()
est disponible dans Chrome pour les tests auprès d'utilisateurs réels dans le cadre d'une phase d'évaluation à partir de la version 121 (publiée en janvier 2024) et jusqu'au 3 septembre 2024.
L'API fetchLater()
const fetchLaterResult = fetchLater(request, options);
fetchLater()
accepte deux arguments, généralement identiques à ceux de fetch()
:
request
, soit une URL de chaîne, soit une instanceRequest
.- Objet
options
facultatif, qui étend leoptions
defetch()
avec un délai avant expiration appeléactivateAfter
.
fetchLater()
renvoie un FetchLaterResult
, qui ne contient actuellement qu'une seule propriété activated
en lecture seule, qui sera définie sur true
une fois que "plus tard" sera passé et que la récupération aura été effectuée. Toute réponse à la requête fetchLater()
est supprimée.
request
L'utilisation la plus simple consiste à utiliser une URL seule :
fetchLater('/endpoint/');
Toutefois, comme pour 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 l'annuler.
fetchLater('/endpoint/', {
method: 'GET',
cache: 'no-store',
mode: 'same-origin',
headers: {Authorization: 'SUPER_SECRET'},
});
options
L'objet options étend les options de fetch()
avec un délai avant expiration, activateAfter
, au cas où vous souhaiteriez déclencher la requête après le délai avant expiration ou lorsque la page est désinstallée, selon la première éventualité.
Vous pouvez ainsi choisir de recevoir les données au dernier moment possible ou au moment le plus opportun.
Par exemple, si vous disposez d'une application que vos utilisateurs laissent généralement ouverte toute la journée de travail, vous pouvez prévoir un délai d'inactivité d'une heure pour obtenir des analyses plus précises, tout en garantissant l'affichage d'une balise si l'utilisateur a quitté le site avant la fin de cette heure. Vous pourrez ensuite configurer un nouveau fetchLater()
pour l'heure d'analyse suivante.
const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});
Exemple d'utilisation
Lorsque vous mesurez les Core Web Vitals sur le terrain, vous pouvez rencontrer un problème : l'une des métriques de performances peut changer jusqu'à ce que l'utilisateur quitte réellement 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 voulez pas risquer de perdre toutes les données de performances en raison d'un balisage défectueux ou incomplet lors du déchargement de la page. Il est parfait pour fetchLater()
.
Dans cet exemple, les métriques sont surveillées à l'aide de la bibliothèque web-vitals.js, et fetchLater()
pour transmettre les résultats à un point de terminaison Analytics:
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 de métrique est reçue, tous les fetchLater()
planifiés existants sont annulés avec un AbortController
, et un nouvel fetchLater()
est créé avec la mise à jour incluse.
Essayer fetchLater()
Comme indiqué, fetchLater()
est disponible dans une phase d'évaluation de l'origine jusqu'à Chrome 126. Pour en savoir plus, consultez Premiers pas avec les phases d'évaluation.
Pour les tests en local, vous pouvez activer fetchLater
à 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 le fetchLater
global est défini avant de l'utiliser :
if (globalThis.fetchLater) {
// Set up beaconing using fetchLater().
// ...
}
Commentaires
Les commentaires des développeurs sont essentiels pour que les nouvelles API Web soient bien conçues. Nous vous invitons donc à signaler les problèmes et à envoyer vos commentaires sur GitHub.