L'API Long Animation Frames (LoAF, prononcée "Lo-Af") est une mise à jour de l'API Long Tasks qui permet de mieux comprendre les mises à jour lentes de l'interface utilisateur (UI). Cela peut être utile pour identifier les images d'animation lentes susceptibles d'affecter la métrique Core Web Vitals Interaction to Next Paint (INP), qui mesure la réactivité, ou pour identifier d'autres à-coups de l'interface utilisateur qui affectent la lissage.
État de l'API
Après une phase d'évaluation de l'origine de Chrome 116 à Chrome 122, l'API LoAF a été publiée à partir de Chrome 123.
Contexte : l'API Long Tasks
L'API Long Animation Frames est une alternative à l'API Long Tasks, qui est disponible dans Chrome depuis un certain temps (depuis Chrome 58). Comme son nom l'indique, l'API Long Task vous permet de surveiller les tâches longues, c'est-à-dire celles qui occupent le thread principal pendant au moins 50 millisecondes. Vous pouvez surveiller les tâches longues à l'aide de l'interface PerformanceLongTaskTiming
, avec un PeformanceObserver
:
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
observer.observe({ type: 'longtask', buffered: true });
Les tâches longues sont susceptibles de provoquer des problèmes de réactivité. Si un utilisateur tente d'interagir avec une page (par exemple, cliquer sur un bouton ou ouvrir un menu), mais que le thread principal s'occupe déjà d'une tâche longue, l'interaction de l'utilisateur est retardée en attendant que cette tâche soit terminée.
Pour améliorer la réactivité, il est souvent conseillé de décomposer les tâches longues. Si chaque tâche longue est décomposée en plusieurs tâches plus petites, il est possible que des tâches plus importantes puissent être exécutées entre elles pour éviter des retards importants dans la réponse aux interactions.
Par conséquent, lorsque vous essayez d'améliorer la réactivité, la première étape consiste souvent à exécuter une trace de performances et à examiner les tâches longues. Vous pouvez le faire à l'aide d'un outil d'audit en laboratoire tel que Lighthouse (qui propose un audit Éviter les longues tâches du thread principal), ou en examinant les tâches longues dans les outils pour les développeurs Chrome.
Les tests en laboratoire sont souvent un mauvais point de départ pour identifier les problèmes de réactivité, car ces outils peuvent ne pas inclure d'interactions. S'ils le font, il s'agit d'un petit sous-ensemble d'interactions probables. Dans l'idéal, vous devriez mesurer les causes des interactions lentes sur le terrain.
Inconvénients de l'API Long Tasks
Mesurer des tâches longues sur le terrain à l'aide d'un observateur de performances n'est que partiellement utile. En réalité, il ne fournit pas beaucoup d'informations, si ce n'est que la tâche a été longue et la durée qu'elle a prise.
Les outils de surveillance des utilisateurs réels (RUM) utilisent souvent cette métrique pour suivre l'évolution du nombre ou de la durée des tâches longues, ou pour identifier les pages sur lesquelles elles se produisent. Toutefois, sans les détails sous-jacents sur la cause de la tâche longue, cette métrique n'est que d'une utilité limitée. L'API Long Tasks ne dispose que d'un modèle d'attribution de base, qui ne vous indique au mieux que le conteneur dans lequel la tâche longue s'est produite (le document de niveau supérieur ou un <iframe>
), mais pas le script ou la fonction qui l'ont appelée, comme le montre une entrée typique :
{
"name": "unknown",
"entryType": "longtask",
"startTime": 31.799999997019768,
"duration": 136,
"attribution": [
{
"name": "unknown",
"entryType": "taskattribution",
"startTime": 0,
"duration": 0,
"containerType": "window",
"containerSrc": "",
"containerId": "",
"containerName": ""
}
]
}
L'API Long Tasks est également incomplète, car elle peut également exclure certaines tâches importantes. Certaines mises à jour, comme le rendu, se produisent dans des tâches distinctes qui devraient idéalement être incluses avec l'exécution précédente à l'origine de cette mise à jour afin de mesurer précisément le "travail total" de cette interaction. Pour en savoir plus sur les limites des tâches, consultez la section "Où les tâches longues échouent" de la vidéo explicative.
Le dernier problème est que la mesure des tâches longues ne fournit des rapports que sur les tâches individuelles qui durent plus de 50 millisecondes. Un frame d'animation peut être composé de plusieurs tâches inférieures à cette limite de 50 millisecondes, mais bloquer collectivement la capacité de rendu du navigateur.
API Long Animation Frames
L'API Long Animation Frames (LoAF) est une nouvelle API qui vise à combler certaines des lacunes de l'API Long Tasks. Elle permet aux développeurs d'obtenir des insights plus exploitables afin de résoudre les problèmes de réactivité et d'améliorer l'INP, ainsi que de mieux comprendre les problèmes de fluidité.
Une bonne réactivité signifie qu'une page répond rapidement aux interactions avec elle. Cela implique de pouvoir peindre toutes les mises à jour nécessaires à l'utilisateur dans les meilleurs délais et d'éviter de bloquer ces mises à jour. Pour les INP, nous vous recommandons de répondre en 200 millisecondes ou moins, mais pour d'autres mises à jour (animations, par exemple), même 200 millisecondes peuvent être trop longues.
L'API Long Animation Frames est une autre approche pour mesurer le travail bloquant. Plutôt que de mesurer les tâches individuelles, l'API Long Animation Frames (comme son nom l'indique) mesure les frames d'animation longs. Un frame d'animation long se produit lorsqu'une mise à jour de rendu est retardée de plus de 50 millisecondes (même seuil que celui de l'API Long Tasks).
Les images d'animation longues sont mesurées à partir du début des tâches qui nécessitent un rendu. Si la première tâche d'un frame d'animation long potentiel ne nécessite pas de rendu, le frame d'animation long est terminé à la fin de la tâche sans rendu, et un nouveau frame d'animation long potentiel est lancé avec la tâche suivante. Ces images d'animation longues sans rendu sont toujours incluses dans l'API Long Animation Frames lorsqu'elles durent plus de 50 millisecondes (avec une durée renderStart
de 0) afin de permettre de mesurer le travail potentiellement bloquant.
Les longues frames d'animation peuvent être observées de la même manière que les tâches longues avec un PerformanceObserver
, mais en examinant le type long-animation-frame
à la place:
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
observer.observe({ type: 'long-animation-frame', buffered: true });
Vous pouvez également interroger les images d'animation longues précédentes à partir de la timeline des performances comme suit :
const loafs = performance.getEntriesByType('long-animation-frame');
Toutefois, il existe un maxBufferSize
pour les entrées de performances, après quoi les entrées plus récentes sont supprimées. L'approche PerformanceObserver est donc recommandée. La taille de la mémoire tampon long-animation-frame
est définie sur 200, comme pour long-tasks
.
Avantages de l'analyse des frames au lieu des tâches
Le principal avantage d'examiner cela du point de vue d'une image plutôt que du point de vue des tâches est qu'une longue animation peut être composée de n'importe quel nombre de tâches ayant entraîné une longue image d'animation. Cela répond au dernier point mentionné précédemment, où la somme de nombreuses petites tâches bloquant le rendu avant un frame d'animation peut ne pas être affichée par l'API Long Tasks.
Autre avantage de cette vue alternative des tâches longues : vous pouvez obtenir une répartition temporelle de l'ensemble du frame. Au lieu d'inclure uniquement un startTime
et un duration
, comme l'API Long Tasks, LoAF inclut une répartition beaucoup plus détaillée des différentes parties de la durée du frame.
Codes temporels et durées des frames
startTime
: heure de début du frame d'animation longue par rapport à l'heure de début de la navigation.duration
: durée du frame d'animation long (sans compter le temps de présentation).renderStart
: heure de début du cycle de rendu, qui comprend les rappelsrequestAnimationFrame
, le calcul du style et de la mise en page, les rappels de l'observateur de redimensionnement et de l'observateur d'intersection.styleAndLayoutStart
: début de la période de calcul du style et de la mise en page.firstUIEventTimestamp
: heure du premier événement d'interface utilisateur (souris/clavier, etc.) à traiter au cours de ce frame.blockingDuration
: durée totale en millisecondes pendant laquelle le frame d'animation bloque le traitement de l'entrée ou d'autres tâches de priorité élevée.
Explication de blockingDuration
Un frame d'animation long peut être composé de plusieurs tâches. blockingDuration
correspond à la somme des durées de tâche supérieures à 50 millisecondes (y compris la durée de rendu finale de la tâche la plus longue).
Par exemple, si une longue image d'animation était composée de deux tâches de 55 millisecondes et 65 millisecondes, suivies d'un rendu de 20 millisecondes, duration
serait d'environ 140 millisecondes avec une blockingDuration
de (55 - 50) + (65 + 20 - 50) = 40 millisecondes. Pendant 40 millisecondes de ce frame d'animation de 140 millisecondes, le frame a été considéré comme bloqué pour la gestion des entrées.
Indique si duration
ou blockingDuration
doit être examiné.
Pour l'affichage commun à 60 Hz, un navigateur tente de planifier un frame au moins toutes les 16,66 ms (pour assurer des mises à jour fluides) ou après une tâche de priorité élevée, comme la gestion des entrées (pour assurer des mises à jour réactives). Toutefois, si aucune entrée ni aucune autre tâche de priorité élevée n'est effectuée, mais qu'une file d'attente d'autres tâches est présente, le navigateur continue généralement le frame actuel bien au-delà de 16,66 millisecondes, quelle que soit la répartition des tâches. Autrement dit, le navigateur essaie toujours de prioriser les entrées, mais peut choisir de s'occuper d'une file d'attente de tâches plutôt que de mettre à jour le rendu. En effet, le rendu est un processus coûteux. Le traitement d'une tâche de rendu combinée pour plusieurs tâches entraîne généralement une réduction globale du travail.
Par conséquent, les images animées longues avec une blockingDuration
faible ou nulle doivent toujours répondre aux entrées. Réduire ou éliminer les blockingDuration
en divisant les tâches longues est donc essentiel pour améliorer la réactivité, telle que mesurée par l'INP.
Toutefois, de nombreux frames d'animation longs, quel que soit le paramètre blockingDuration
, indiquent des mises à jour de l'UI retardées, ce qui peut toujours affecter la fluidité et donner l'impression d'une interface utilisateur lente pour le défilement ou les animations, même si ces éléments sont moins problématiques pour la réactivité mesurée par l'INP. Pour comprendre les problèmes dans ce domaine, examinez les duration
. Toutefois, ceux-ci peuvent être plus difficiles à optimiser, car vous ne pouvez pas les résoudre en divisant le travail, mais en le réduisant.
Temps de rendu
Les codes temporels mentionnés précédemment permettent de diviser le frame d'animation long en codes temporels :
Durée | Calcul |
---|---|
Heure de début | startTime |
Heure de fin | startTime + duration |
Durée de la tâche | renderStart ? renderStart - startTime : duration |
Durée du rendu | renderStart ? (startTime + duration) - renderStart: 0 |
Rendu: durée de prémise en page | styleAndLayoutStart ? styleAndLayoutStart - renderStart : 0 |
Rendu: durée du style et de la mise en page | styleAndLayoutStart ? (startTime + duration) - styleAndLayoutStart : 0 |
Meilleure attribution des scripts
Le type d'entrée long-animation-frame
inclut de meilleures données d'attribution pour chaque script ayant contribué à un frame d'animation long (pour les scripts de plus de cinq millisecondes).
Comme pour l'API Long Tasks, ces données seront fournies dans un tableau d'entrées d'attribution, chacune contenant les informations suivantes:
name
etEntryType
renvoient tous les deuxscript
.- Un
invoker
significatif, indiquant comment le script a été appelé (par exemple,'IMG#id.onload'
,'Window.requestAnimationFrame'
ou'Response.json.then'
). invokerType
du point d'entrée du script :user-callback
: rappel connu enregistré à partir d'une API de plate-forme Web (par exemple,setTimeout
,requestAnimationFrame
).event-listener
: écouteur d'un événement de plate-forme (par exemple,click
,load
,keyup
).resolve-promise
: gestionnaire d'une promesse de plate-forme (par exemple,fetch()
). Notez que dans le cas des promesses, tous les gestionnaires des mêmes promesses sont mélangés dans un seul "script"..
reject-promise
: conformément àresolve-promise
, mais pour le refus.classic-script
: évaluation du script (par exemple,<script>
ouimport()
)module-script
: identique àclassic-script
, mais pour les scripts de module.
- Données de synchronisation distinctes pour ce script :
startTime
: heure à laquelle la fonction d'entrée a été appelée.duration
: durée entrestartTime
et la fin du traitement de la file de microtâches suivante.executionStart
: heure après la compilation.forcedStyleAndLayoutDuration
: temps total passé à traiter la mise en page et le style forcés dans cette fonction (voir thrashing).pauseDuration
: temps total passé à "mettre en pause" les opérations synchrones (alerte, XHR synchrone).
- Détails de la source du script :
sourceURL
: nom de la ressource de script, le cas échéant (ou vide si elle n'est pas trouvée).sourceFunctionName
: nom de la fonction de script, le cas échéant (ou vide si elle n'est pas trouvée).sourceCharPosition
: position du caractère du script, le cas échéant (ou -1 si aucun caractère n'est trouvé).
windowAttribution
: conteneur (document de niveau supérieur ou<iframe>
) dans lequel le frame d'animation long s'est produit.window
: référence à la fenêtre de même origine.
Le cas échéant, les entrées source permettent aux développeurs de savoir exactement comment chaque script du frame d'animation long a été appelé, jusqu'à la position du caractère dans le script appelant. Cela indique l'emplacement exact dans une ressource JavaScript qui a entraîné le long frame d'animation.
Exemple d'entrée de performances long-animation-frame
Voici un exemple complet d'entrée de performance long-animation-frame
contenant un seul script:
{
"blockingDuration": 0,
"duration": 60,
"entryType": "long-animation-frame",
"firstUIEventTimestamp": 11801.099999999627,
"name": "long-animation-frame",
"renderStart": 11858.800000000745,
"scripts": [
{
"duration": 45,
"entryType": "script",
"executionStart": 11803.199999999255,
"forcedStyleAndLayoutDuration": 0,
"invoker": "DOMWindow.onclick",
"invokerType": "event-listener",
"name": "script",
"pauseDuration": 0,
"sourceURL": "https://web.dev/js/index-ffde4443.js",
"sourceFunctionName": "myClickHandler",
"sourceCharPosition": 17796,
"startTime": 11803.199999999255,
"window": [Window object],
"windowAttribution": "self"
}
],
"startTime": 11802.400000000373,
"styleAndLayoutStart": 11858.800000000745
}
Comme vous pouvez le constater, cela fournit aux sites Web une quantité de données sans précédent pour comprendre la cause des mises à jour de rendu lentes.
Utiliser l'API Long Animation Frames dans le champ
Des outils tels que Chrome DevTools et Lighthouse, bien qu'utiles pour découvrir et reproduire des problèmes, sont des outils de laboratoire qui peuvent manquer d'aspects importants de l'expérience utilisateur que seules les données sur le terrain peuvent fournir.
L'API Long Animation Frames est conçue pour être utilisée sur le terrain afin de collecter des données contextuelles importantes pour les interactions utilisateur que l'API Long Tasks ne pouvait pas. Cela peut vous aider à identifier et à reproduire les problèmes d'interactivité que vous n'auriez peut-être pas découverts autrement.
Prise en charge de la fonctionnalité de détection des frames d'animation longs avec l'API
Vous pouvez utiliser le code suivant pour vérifier si l'API est compatible :
if (PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')) {
// Monitor LoAFs
}
Lien vers l'interaction INP la plus longue
Le cas d'utilisation le plus évident de l'API Long Animation Frames consiste à aider à diagnostiquer et à résoudre les problèmes d'Interaction to Next Paint (INP). C'est l'une des principales raisons pour lesquelles l'équipe Chrome a développé cette API. Un INP de qualité est celui où toutes les interactions sont traitées en 200 millisecondes ou moins, de l'interaction jusqu'à la peinture du frame. Étant donné que l'API Long Animation Frames mesure tous les frames qui prennent 50 ms ou plus, la plupart des INP problématiques doivent inclure des données LoAF pour vous aider à diagnostiquer ces interactions.
La "LoAF INP" est la LoAF qui inclut l'interaction INP, comme illustré dans le diagramme suivant :
Dans certains cas, il est possible qu'un événement INP couvre deux LOAF, généralement si l'interaction se produit après que l'image a lancé la partie de rendu du frame précédent, et que le gestionnaire d'événements est donc traité dans l'image suivante:
Dans de rares cas, il est même possible qu'il couvre plus de deux LOAF.
Enregistrer les données des LoAF associées à l'interaction INP vous permet d'obtenir beaucoup plus d'informations sur l'interaction INP pour la diagnostiquer. Cela est particulièrement utile pour comprendre le délai d'entrée, car vous pouvez voir quels autres scripts étaient exécutés dans ce frame.
Il peut également être utile de comprendre les durées de traitement et retards de présentation inexpliquées si vos gestionnaires d'événements ne reproduisent pas les valeurs observées pour ces éléments, car d'autres scripts peuvent s'exécuter pour vos utilisateurs et ne pas être inclus dans vos propres tests.
Il n'existe aucune API directe permettant d'associer une entrée INP à une ou plusieurs entrées LoAF associées, mais vous pouvez le faire dans le code en comparant les heures de début et de fin de chacune (voir l'exemple de script WhyNp). La bibliothèque web-vitals
inclut tous les LoAF qui se croisent dans la propriété longAnimationFramesEntries
de l'interface d'attribution INP à partir de la version 4.
Une fois que vous avez associé l'entrée ou les entrées de la liste d'attente d'autorisation, vous pouvez inclure des informations avec une attribution INP. L'objet scripts
contient certaines des informations les plus précieuses, car il peut indiquer ce qui s'exécute dans ces frames. Ainsi, en renvoyant ces données à votre service d'analyse, vous pourrez mieux comprendre pourquoi les interactions étaient lentes.
Signaler les erreurs de non-fonctionnement pour l'interaction INP est un bon moyen de trouver les problèmes d'interactivité les plus urgents sur votre page. Chaque utilisateur peut interagir différemment avec votre page. Si vous disposez d'un volume suffisant de données d'attribution par INP, un certain nombre de problèmes potentiels seront inclus dans ces données. Vous pouvez ainsi trier les scripts par volume pour voir ceux qui sont associés à une vitesse d'importation des données lentes.
Signaler des données d'animation plus longues à un point de terminaison d'analyse
L'inconvénient de ne regarder que les avertissements de non-conformité de l'INP est que vous risquez de passer à côté d'autres axes d'amélioration potentiels qui pourraient entraîner des problèmes d'INP à l'avenir. Vous pouvez alors avoir l'impression de tourner en rond. Vous corrigez un problème d'INP en vous attendant à une amélioration considérable, mais vous constatez que l'interaction la plus lente suivante n'est que légèrement meilleure, ce qui n'améliore pas beaucoup votre INP.
Plutôt que de vous concentrer uniquement sur la métrique LoAF de l'INP, vous pouvez envisager de prendre en compte toutes les métriques LoAF sur la durée de vie de la page :
Cependant, chaque entrée LoAF contient énormément de données, il est donc probable que vous souhaitiez limiter votre analyse à certains d'entre eux uniquement. De plus, comme les entrées de cadres d'animation longues peuvent être très volumineuses, les développeurs doivent décider quelles données de l'entrée doivent être envoyées à l'analyse. Par exemple, les heures récapitulatives de l'entrée et peut-être les noms des scripts, ou tout autre ensemble minimal d'autres données contextuelles pouvant être jugées nécessaires.
Voici quelques suggestions pour réduire la quantité de données de longues images d'animation:
- Observer les frames d'animation longs avec des interactions
- Observer des images d'animation longues avec des durées de blocage élevées
- Observer les longues images d'animation lors des mises à jour critiques de l'interface utilisateur pour améliorer la fluidité
- Observer les pires images d'animation longues
- Identifier les tendances courantes dans les longues images d'animation
Le modèle qui vous convient le mieux dépend de votre niveau d'optimisation et de la fréquence des images d'animation longues. Pour un site qui n'a jamais été optimisé pour la réactivité auparavant, il peut y avoir de nombreuses erreurs de chargement lent. Vous pouvez donc vous limiter aux erreurs de chargement lent avec interactions, définir un seuil élevé ou n'examiner que les plus graves.
À mesure que vous résoudrez les problèmes de réactivité courants, vous pouvez étendre cette fonctionnalité en ne vous limitant pas aux interactions ou aux durées de blocage élevées, ou en réduisant les seuils.
Observer les frames d'animation longs avec des interactions
Pour obtenir des insights au-delà de la longue image d'animation INP, vous pouvez examiner tous les LOAF avec des interactions (qui peuvent être détectées par la présence d'une valeur firstUIEventTimestamp
) avec une blockingDuration
élevée.
Il peut également s'agir d'une méthode plus simple pour surveiller les enregistrements de l'INP plutôt que d'essayer de les mettre en corrélation, ce qui peut être plus complexe. Dans la plupart des cas, cela inclut l'INP hors connexion pour une visite donnée. Dans de rares cas, il n'en est pas ainsi, mais des interactions longues qui doivent être corrigées sont tout de même détectées, car elles peuvent être l'interaction INP pour d'autres utilisateurs.
Le code suivant consigne toutes les entrées LoAF avec un blockingDuration
supérieur à 100 millisecondes où une interaction s'est produite pendant le frame. Le nombre 100 est choisi ici, car il est inférieur au seuil d'INP "bon" de 200 ms. Vous pouvez choisir une valeur plus élevée ou plus faible en fonction de vos besoins.
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
if (entry.blockingDuration > REPORTING_THRESHOLD_MS &&
entry.firstUIEventTimestamp > 0
) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
Observer des cadres d'animation longs avec des durées de blocage élevées
Au lieu d'examiner tous les frames d'animation longs avec des interactions, vous pouvez examiner tous les frames d'animation longs avec des durées de blocage élevées. Ils indiquent des problèmes potentiels d'entrée utilisateur si un utilisateur interagit pendant ces longs frames d'animation.
Le code suivant consigne toutes les entrées LoAF dont la durée de blocage est supérieure à 100 millisecondes et pour lesquelles une interaction s'est produite pendant le frame. La valeur 100 est choisie ici, car elle est inférieure au seuil d'INP "bon" de 200 millisecondes pour aider à identifier les images problématiques potentielles, tout en limitant au minimum le nombre d'images d'animation longues signalées. Vous pouvez choisir une valeur plus élevée ou plus faible en fonction de vos besoins.
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
if (entry.blockingDuration > REPORTING_THRESHOLD_MS) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
Observer les longs frames d'animation lors des mises à jour critiques de l'UI pour améliorer la fluidité
Comme indiqué précédemment, examiner les frames d'animation longs à durée de blocage élevée peut vous aider à améliorer la réactivité des entrées. Toutefois, pour une fluidité optimale, vous devez examiner tous les frames d'animation longs avec un duration
long.
Comme cela peut générer beaucoup de bruit, vous pouvez limiter les mesures de ces valeurs aux points clés en utilisant un modèle comme celui-ci:
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
if (measureImportantUIupdate) {
for (const entry of list.getEntries()) {
if (entry.duration > REPORTING_THRESHOLD_MS) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
async function doUIUpdatesWithMeasurements() {
measureImportantUIupdate = true;
await doUIUpdates();
measureImportantUIupdate = false;
}
Observer les pires frames d'animation longue
Plutôt que de définir un seuil, les sites peuvent choisir de collecter des données sur le ou les frames d'animation les plus longs afin de réduire le volume de données à diffuser par balise. Ainsi, quel que soit le nombre de longues animations affichées sur une page, seules les données correspondant au pire, cinq, dix ou le nombre de longues animations absolument nécessaires sont renvoyées.
MAX_LOAFS_TO_CONSIDER = 10;
let longestBlockingLoAFs = [];
const observer = new PerformanceObserver(list => {
longestBlockingLoAFs = longestBlockingLoAFs.concat(list.getEntries()).sort(
(a, b) => b.blockingDuration - a.blockingDuration
).slice(0, MAX_LOAFS_TO_CONSIDER);
});
observer.observe({ type: 'long-animation-frame', buffered: true });
Ces stratégies peuvent également être combinées : vous ne pouvez examiner que les 10 manchots de faible niveau d'engagement de plus de 100 millisecondes, avec des interactions de plus de 100 millisecondes.
Au moment opportun (idéalement lors de l'événement visibilitychange
), le balise renvoie les données à Analytics. Pour les tests en local, vous pouvez utiliser régulièrement console.table
:
console.table(longestBlockingLoAFs);
Identifier les modèles courants dans les images animées longues
Une autre stratégie consiste à examiner les scripts courants qui apparaissent le plus souvent dans les entrées de frames d'animation longues. Les données peuvent être rapportées au niveau du script et de la position des personnages afin d'identifier les responsables d'infractions répétées.
Cette approche peut être particulièrement efficace pour les plates-formes personnalisables, où les thèmes ou les plug-ins à l'origine de problèmes de performances peuvent être identifiés sur plusieurs sites.
Le temps d'exécution des scripts courants (ou des origines tierces) dans les frames d'animation longs peut être résumé et signalé pour identifier les contributeurs courants aux frames d'animation longs sur un site ou un ensemble de sites. Par exemple, pour consulter les URL:
const observer = new PerformanceObserver(list => {
const allScripts = list.getEntries().flatMap(entry => entry.scripts);
const scriptSource = [...new Set(allScripts.map(script => script.sourceURL))];
const scriptsBySource= scriptSource.map(sourceURL => ([sourceURL,
allScripts.filter(script => script.sourceURL === sourceURL)
]));
const processedScripts = scriptsBySource.map(([sourceURL, scripts]) => ({
sourceURL,
count: scripts.length,
totalDuration: scripts.reduce((subtotal, script) => subtotal + script.duration, 0)
}));
processedScripts.sort((a, b) => b.totalDuration - a.totalDuration);
// Example here logs to console, but could also report back to analytics
console.table(processedScripts);
});
observer.observe({type: 'long-animation-frame', buffered: true});
Voici un exemple de résultat:
(index) |
sourceURL |
count |
totalDuration |
---|---|---|---|
0 |
'https://example.consent.com/consent.js' |
1 |
840 |
1 |
'https://example.com/js/analytics.js' |
7 |
628 |
2 |
'https://example.chatapp.com/web-chat.js' |
1 |
5 |
Utiliser l'API Long Animation Frames dans les outils
L'API permet également d'utiliser des outils de développement supplémentaires pour le débogage local. Bien que certains outils tels que Lighthouse et Chrome DevTools aient pu collecter une grande partie de ces données à l'aide de détails de traçage de bas niveau, la présence de cette API de niveau supérieur pourrait permettre à d'autres outils d'accéder à ces données.
Afficher les données des longues frames d'animation dans les outils de développement
Vous pouvez afficher des frames d'animation longs dans DevTools à l'aide de l'API performance.measure()
, qui sont ensuite affichés dans la piste de temps utilisateur DevTools dans les traces de performances pour vous indiquer où concentrer vos efforts afin d'améliorer les performances. Grâce à l'API d'extensibilité DevTools, vous pouvez même les afficher dans leur propre canal:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
performance.measure('LoAF', {
start: entry.startTime,
end: entry.startTime + entry.duration,
detail: {
devtools: {
dataType: "track-entry",
track: "Long animation frames",
trackGroup: "Performance Timeline",
color: "tertiary-dark",
tooltipText: 'LoAF'
}
}
});
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
À plus long terme, les frames d'animation longs seront probablement intégrés aux outils pour les développeurs eux-mêmes, mais l'extrait de code précédent permet de les afficher en attendant.
La première entrée de la figure précédente montre également où le navigateur a traité plusieurs tâches ensemble dans le même frame d'animation long au lieu de les afficher entre elles. Comme indiqué précédemment, cela peut se produire lorsqu'il n'y a pas de tâches d'entrée à priorité élevée, mais qu'il existe une file d'attente de tâches. La première tâche longue doit effectuer des mises à jour de rendu (sinon, le frame d'animation long actuel serait réinitialisé après, et un nouveau commencerait avec la tâche suivante). Toutefois, au lieu d'exécuter immédiatement ce rendu, le navigateur a traité un certain nombre de tâches supplémentaires, puis seulement exécuté la tâche de rendu longue et mis fin au frame d'animation long. Cela montre l'utilité d'examiner les frames d'animation longs dans les outils de développement, plutôt que de se contenter de tâches longues, pour identifier les rendus retardés.
Utiliser les données des frames d'animation longues dans d'autres outils de développement
L'extension Web Vitals a affiché la valeur dans les informations de débogage du résumé de journalisation pour diagnostiquer les problèmes de performances.
Désormais, il affiche également de longues données d'images d'animation pour chaque rappel INP et chaque interaction:
Utiliser les données des frames d'animation longues dans les outils de test automatisés
De même, les outils de test automatisés des pipelines CI/CD peuvent fournir des informations sur les problèmes de performances potentiels en mesurant les frames d'animation longs lors de l'exécution de diverses suites de tests.
Questions fréquentes
Voici quelques questions fréquentes sur cette API :
Pourquoi ne pas simplement étendre ou itérer sur l'API Long Tasks ?
Il s'agit d'une autre façon de mesurer les problèmes de réactivité potentiels, même si la mesure est similaire. Il est important de s'assurer que les sites qui dépendent de l'API Long Tasks existante continuent de fonctionner pour éviter de perturber les cas d'utilisation existants.
Bien que l'API Long Tasks puisse bénéficier de certaines fonctionnalités de LoAF (comme un meilleur modèle d'attribution), nous pensons que se concentrer sur les frames plutôt que sur les tâches offre de nombreux avantages qui font de cette API une API fondamentalement différente de l'API Long Tasks existante.
Why do I not have script entries?
Cela peut indiquer que le frame d'animation long n'était pas dû à JavaScipt, mais à un travail de rendu important.
Cela peut également se produire lorsque le frame d'animation long est dû à JavaScript, mais que l'attribution du script ne peut pas être fournie pour diverses raisons de confidentialité, comme indiqué précédemment (principalement parce que le code JavaScript n'appartient pas à la page).
Pourquoi y a-t-il des entrées de script, mais aucune information source ou des informations limitées ?
Cela peut se produire pour plusieurs raisons, y compris si aucune source appropriée n'est disponible.
Les informations sur les scripts seront également limitées pour les scripts no-cors cross-origin
. Toutefois, vous pouvez résoudre ce problème en extrayant ces scripts à l'aide de CORS en ajoutant crossOrigin = "anonymous"
à l'appel <script>
.
Par exemple, voici le script Google Tag Manager par défaut à ajouter à la page:
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->
Il peut être amélioré pour ajouter des j.crossOrigin = "anonymous"
afin de permettre de fournir tous les détails de l'attribution pour GTM.
Cette API remplacera-t-elle l'API Long Tasks ?
Nous pensons que l'API Long Animation Frames est une API plus performante et plus complète pour mesurer les longues tâches. Toutefois, nous ne prévoyons pas d'abandonner l'API Long Tasks pour le moment.
Commentaires souhaités
Vous pouvez envoyer vos commentaires sur la liste des problèmes GitHub ou signaler les bugs dans l'implémentation de l'API dans Chrome dans le outil de suivi des problèmes de Chrome.
Conclusion
L'API Long Animation Frames est une nouvelle API intéressante qui présente de nombreux avantages potentiels par rapport à l'ancienne API Long Tasks.
Il s’avère qu’il s’agit d’un outil clé pour résoudre les problèmes de réactivité tels que mesurés par INP. L'INP est une métrique difficile à optimiser. L'équipe Chrome cherche à faciliter l'identification et la résolution des problèmes grâce à cette API.
L'API Long Animation Frames ne se limite pas aux INP. Elle peut vous aider à identifier d'autres causes de mises à jour lentes qui peuvent affecter la fluidité globale de l'expérience utilisateur d'un site Web.