Die Long Animation Frames API (LoAF-ausgesprochen Lo-Af) ist ein Update für die Long Tasks API, um langsame Aktualisierungen der Benutzeroberfläche (UI) besser zu verstehen. Das kann hilfreich sein, um langsame Animationsframes zu identifizieren, die sich wahrscheinlich auf den Core Web Vital-Messwert Interaction to Next Paint (INP) auswirken, mit dem die Reaktionsfähigkeit gemessen wird, oder um andere Ruckler in der Benutzeroberfläche zu identifizieren, die sich auf die Glaubwürdigkeit auswirken.
Status der API
Nach einem Ursprungstest von Chrome 116 bis Chrome 122 wurde die LoAF API ab Chrome 123 eingeführt.
Hintergrund: Long Tasks API
Die Long Animation Frames API ist eine Alternative zur Long Tasks API, die seit Chrome 58 in Chrome verfügbar ist. Wie der Name schon sagt, können Sie mit der Long Task API lange Aufgaben überwachen, also Aufgaben, die den Haupt-Thread mindestens 50 Millisekunden lang belegen. Lange Aufgaben können über die PerformanceLongTaskTiming
-Oberfläche mit einem PeformanceObserver
überwacht werden:
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
observer.observe({ type: 'longtask', buffered: true });
Lange Aufgaben führen wahrscheinlich zu Problemen mit der Reaktionsfähigkeit. Wenn ein Nutzer versucht, mit einer Seite zu interagieren, z. B. auf eine Schaltfläche zu klicken oder ein Menü zu öffnen, der Hauptthread aber bereits mit einer langen Aufgabe beschäftigt ist, wird die Interaktion des Nutzers verzögert, bis diese Aufgabe abgeschlossen ist.
Um die Reaktionsfähigkeit zu verbessern, wird oft empfohlen, lange Aufgaben aufzuteilen. Wenn jede lange Aufgabe stattdessen in eine Reihe mehrerer, kleinerer Aufgaben aufgeteilt wird, können wichtigere Aufgaben zwischen ihnen ausgeführt werden, um erhebliche Verzögerungen bei der Reaktion auf Interaktionen zu vermeiden.
Wenn Sie also die Reaktionsfähigkeit verbessern möchten, besteht der erste Anhaltspunkt oft darin, eine Leistungs-Trace auszuführen und sich lange Aufgaben anzusehen. Das kann über ein Lab-basiertes Auditing-Tool wie Lighthouse (mit der Prüfung Lange Hauptthreadaufgaben vermeiden) oder durch Ansehen langer Aufgaben in den Chrome-Entwicklertools erfolgen.
Labbasierte Tests sind häufig ein schlechter Ausgangspunkt, um Probleme mit der Reaktionsfähigkeit zu erkennen, da diese Tools möglicherweise keine Interaktionen enthalten. Wenn sie dies tun, stellen sie einen kleinen Teil der wahrscheinlichen Interaktionen dar. Im Idealfall sollten Sie die Ursachen für langsame Interaktionen vor Ort messen.
Nachteile der Long Tasks API
Das Messen langer Aufgaben im Feld mit einem Leistungs-Observer ist nur bedingt sinnvoll. In Wirklichkeit gibt es nicht viele Informationen darüber, außer dass eine lange Aufgabe stattgefunden hat und wie lange sie gedauert hat.
Mithilfe von Real User Monitoring (RUM)-Tools werden häufig Trends bei der Anzahl oder Dauer langer Aufgaben ermittelt oder die Seiten identifiziert, auf denen sie auftreten. Ohne die zugrunde liegenden Details zur Ursache der langen Aufgabe ist dies jedoch nur von begrenztem Nutzen. Die Long Tasks API hat nur ein einfaches Attributionsmodell, das bestenfalls nur den Container angibt, in dem die lange Aufgabe ausgeführt wurde (das Dokument der obersten Ebene oder eine <iframe>
), aber nicht das Script oder die Funktion, die sie aufgerufen hat. Das ist an einem typischen Eintrag zu sehen:
{
"name": "unknown",
"entryType": "longtask",
"startTime": 31.799999997019768,
"duration": 136,
"attribution": [
{
"name": "unknown",
"entryType": "taskattribution",
"startTime": 0,
"duration": 0,
"containerType": "window",
"containerSrc": "",
"containerId": "",
"containerName": ""
}
]
}
Die Long Tasks API ist ebenfalls unvollständig, da einige wichtige Aufgaben möglicherweise ausgeschlossen werden. Einige Aktualisierungen, z. B. das Rendering, erfolgen in separaten Aufgaben, die idealerweise zusammen mit der vorherigen Ausführung, die diese Aktualisierung verursacht hat, enthalten sein sollten, um die „Gesamtarbeit“ für diese Interaktion genau zu messen. Weitere Informationen zu den Einschränkungen, die sich aus der Abhängigkeit von Aufgaben ergeben, finden Sie im Abschnitt Wozu lange Aufgaben bestehen? der Erklärung.
Das letzte Problem ist, dass bei der Messung langer Aufgaben nur einzelne Aufgaben erfasst werden, die länger als 50 Millisekunden dauern. Ein Animationsframe kann aus mehreren Aufgaben bestehen, die kürzer als 50 Millisekunden sind, aber gemeinsam das Rendern des Browsers blockieren.
Long Animation Frames API
Die Long Animation Frames API (LoAF) ist eine neue API, mit der einige der Mängel der Long Tasks API behoben werden sollen. So erhalten Entwickler umsetzbarere Informationen, um Probleme mit der Reaktionsfähigkeit zu beheben und die INP zu verbessern. Außerdem erhalten sie Informationen zu Problemen mit der Laufruhe.
Eine gute Reaktionsfähigkeit bedeutet, dass eine Seite schnell auf Interaktionen reagiert. Dazu gehört, dass Sie alle vom Nutzer benötigten Updates rechtzeitig darstellen und vermeiden können, dass diese Updates blockiert werden. Für INP wird eine Reaktionszeit von maximal 200 Millisekunden empfohlen. Bei anderen Aktualisierungen (z. B. Animationen) sind aber selbst 200 Millisekunden möglicherweise zu lang.
Die Long Animation Frames API ist eine alternative Methode zur Messung blockierender Arbeit. Anstatt die einzelnen Aufgaben zu messen, werden mit der Long Animation Frames API – wie der Name schon sagt – lange Animationsframes gemessen. Ein langer Animationsframe liegt vor, wenn eine Renderingaktualisierung länger als 50 Millisekunden verzögert ist (derselbe Grenzwert wie für die Long Tasks API).
Lange Animationsframes werden ab dem Beginn von Aufgaben gemessen, die ein Rendern erfordern. Wenn für die erste Aufgabe in einem potenziellen langen Animationsframe kein Rendern erforderlich ist, wird der lange Animationsframe nach Abschluss der Aufgabe ohne Rendering beendet und ein neuer potenzieller langer Animationsframe mit der nächsten Aufgabe gestartet. Solche nicht rendernden langen Animationsframes sind immer noch in der Long Animation Frames API enthalten, wenn sie länger als 50 Millisekunden (mit einer renderStart
-Zeit von 0) sind, um die Messung der potenziell blockierenden Arbeit zu ermöglichen.
Lange Animationsframes können ähnlich wie lange Aufgaben mit einem PerformanceObserver
beobachtet werden, wobei stattdessen der Typ long-animation-frame
betrachtet wird:
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
observer.observe({ type: 'long-animation-frame', buffered: true });
So können Sie auch vorherige lange Animationsframes aus der Leistungszeitachse abfragen:
const loafs = performance.getEntriesByType('long-animation-frame');
Es gibt jedoch eine maxBufferSize
für Leistungseinträge, nach der neuere Einträge gelöscht werden. Daher wird der PerformanceObserver-Ansatz empfohlen. Die Puffergröße für long-animation-frame
ist auf 200 festgelegt, genau wie für long-tasks
.
Vorteile der Betrachtung von Frames anstelle von Aufgaben
Der Hauptvorteil dieser Betrachtungsweise aus der Perspektive des Frames statt der Aufgaben besteht darin, dass eine lange Animation aus beliebig vielen Aufgaben bestehen kann, die zusammen zu einem langen Animationsframe führen. Dies behebt den letzten oben genannten Punkt, bei dem die Summe vieler kleinerer, renderblockierender Aufgaben vor einem Animationsframe möglicherweise nicht von der Long Tasks API erfasst wird.
Ein weiterer Vorteil dieser alternativen Ansicht für lange Aufgaben ist die Möglichkeit, eine Aufschlüsselung der Zeit für den gesamten Frame bereitzustellen. Anstatt nur startTime
und duration
wie bei der Long Tasks API enthält LoAF eine viel detailliertere Aufschlüsselung der verschiedenen Teile der Framedauer.
Zeitstempel und Dauer von Frames
startTime
: die Startzeit des langen Animationsframes relativ zur Navigationsstartzeit.duration
: die Dauer des langen Animationsframes (ohne Präsentationszeit).renderStart
: die Startzeit des Rendering-Zyklus, einschließlichrequestAnimationFrame
-Callbacks, Stil- und Layoutberechnung, Resize-Observer- und Intersection-Observer-Callbacks.styleAndLayoutStart
: Der Beginn des Zeitraums, in dem Stil- und Layoutberechnungen ausgeführt wurden.firstUIEventTimestamp
: die Zeit des ersten UI-Ereignisses (Maus/Tastatur usw.), das im Verlauf dieses Frames verarbeitet werden soll.blockingDuration
: die Gesamtdauer in Millisekunden, für die der Animationsframe die Verarbeitung von Eingaben oder anderen Aufgaben mit hoher Priorität blockiert.
Eine Erklärung zu blockingDuration
Ein langer Animationsframe kann aus mehreren Aufgaben bestehen. blockingDuration
ist die Summe der Aufgabendauern, die länger als 50 Millisekunden sind, einschließlich der endgültigen Renderingdauer innerhalb der längsten Aufgabe.
Wenn ein langer Animationsframe beispielsweise aus zwei Aufgaben mit 55 Millisekunden und 65 Millisekunden besteht, gefolgt von einem Rendern von 20 Millisekunden, beträgt die duration
etwa 140 Millisekunden mit einer blockingDuration
von (55 − 50) + (65 + 20 − 50) = 40 Millisekunden. Während dieses 140 Millisekunden langen Animationsframes wurde der Frame 40 Millisekunden lang als blockiert für die Verarbeitung von Eingaben betrachtet.
Ob duration
oder blockingDuration
betrachtet werden soll
Bei einem 60-Hertz-Display versucht ein Browser, mindestens alle 16,66 Millisekunden einen Frame zu planen (um flüssige Updates zu ermöglichen) oder nach einer Aufgabe mit hoher Priorität wie der Eingabeverarbeitung (um responsive Updates zu ermöglichen). Wenn es jedoch keine Eingaben und keine anderen Aufgaben mit hoher Priorität gibt, aber eine Warteschlange mit anderen Aufgaben vorhanden ist, führt der Browser den aktuellen Frame in der Regel weit über 16,66 Millisekunden hinaus fort, unabhängig davon, wie gut die Aufgaben darin aufgeteilt sind. Das heißt, der Browser versucht immer, Eingaben zu priorisieren, kann aber auch eine Aufgabenliste anstelle von Rendering-Aktualisierungen bearbeiten. Das liegt daran, dass das Rendering ein kostspieliger Prozess ist. Daher führt die Verarbeitung einer kombinierten Rendering-Aufgabe für mehrere Aufgaben in der Regel zu einer Gesamtreduzierung des Arbeitsaufwands.
Daher sollten lange Animationsframes mit einem niedrigen oder nullwertigen blockingDuration
immer noch reaktionsschnell auf Eingaben reagieren. Das Reduzieren oder Entfernen von blockingDuration
durch Aufteilen langer Aufgaben ist daher entscheidend, um die Reaktionsfähigkeit gemäß INP-Messung zu verbessern.
Viele lange Animationsframes, unabhängig von blockingDuration
, deuten jedoch auf verzögerte UI-Aktualisierungen hin, die sich dennoch auf die Laufruhe auswirken und zu einer verzögerten Benutzeroberfläche beim Scrollen oder bei Animationen führen können, auch wenn dies für die Reaktionsfähigkeit, gemessen anhand des INP, weniger problematisch ist. Um Probleme in diesem Bereich zu verstehen, sehen Sie sich die duration
an. Diese lassen sich jedoch schwieriger optimieren, da Sie das Problem nicht durch Aufteilen der Arbeit lösen können, sondern die Arbeit reduzieren müssen.
Frame-Timings
Mit den zuvor erwähnten Zeitstempeln kann der lange Animationsframe in Zeiträume unterteilt werden:
Timing | Berechnung |
---|---|
Beginn | startTime |
Ende | startTime + duration |
Arbeitsdauer | renderStart ? renderStart - startTime : duration |
Renderingdauer | renderStart ? (startTime + duration) - renderStart: 0 |
Rendern: Dauer vor dem Layout | styleAndLayoutStart ? styleAndLayoutStart - renderStart : 0 |
Rendering: Stil und Layoutdauer | styleAndLayoutStart ? (startTime + duration) - styleAndLayoutStart : 0 |
Bessere Scriptzuordnung
Der long-animation-frame
-Eintragstyp enthält bessere Attributionsdaten für jedes Script, das zu einem langen Animationsframe beigetragen hat (für Scripts, die länger als 5 Millisekunden sind).
Ähnlich wie bei der Long Tasks API wird diese in einem Array von Attributionseinträgen bereitgestellt, die jeweils folgende Details enthalten:
- Sowohl
name
als auchEntryType
gebenscript
zurück. - Eine aussagekräftige
invoker
, die angibt, wie das Script aufgerufen wurde (z. B.'IMG#id.onload'
,'Window.requestAnimationFrame'
oder'Response.json.then'
). - Die
invokerType
des Script-Einstiegspunkts:user-callback
: Ein bekannter Callback, der über eine Webplattform-API registriert wurde (z. B.setTimeout
,requestAnimationFrame
).event-listener
: Ein Listener für ein Plattformereignis (z. B.click
,load
,keyup
).resolve-promise
: Handler eines Plattformversprechens (z. B.fetch()
. Im Fall von Promis werden alle Handler derselben Promis als ein Script zusammengeführt..
reject-promise
: Wie beiresolve-promise
, aber für die Ablehnung.classic-script
: Scriptauswertung (z. B.<script>
oderimport()
)module-script
: Entsprichtclassic-script
, aber für Modulscripts.
- Separate Zeitdaten für das Skript:
startTime
: Zeitpunkt, zu dem die Eintragsfunktion aufgerufen wurde.duration
: Der Zeitraum zwischen demstartTime
und dem Zeitpunkt, zu dem die Verarbeitung der nachfolgenden Microtask-Warteschlange abgeschlossen ist.executionStart
: Die Zeit nach der Kompilierung.forcedStyleAndLayoutDuration
: Die Gesamtzeit, die für die Verarbeitung des erzwungenen Layouts und Stils in dieser Funktion aufgewendet wird (siehe Überlastung).pauseDuration
: Gesamtzeit, die für die Pausierung synchroner Vorgänge (Benachrichtigung, synchrone XHR) aufgewendet wurde.
- Details zur Skriptquelle:
sourceURL
: Der Name der Scriptressource, sofern verfügbar (leer, wenn nicht gefunden).sourceFunctionName
: Der Name der Scriptfunktion, sofern verfügbar (leer, wenn nicht gefunden).sourceCharPosition
: Die Zeichenposition des Skripts, falls verfügbar (oder -1, wenn sie nicht gefunden wurde).
windowAttribution
: Der Container (das Dokument auf oberster Ebene oder ein<iframe>
), in dem der lange Animationsframe aufgetreten ist.window
: Eine Referenz auf das Fenster mit demselben Ursprung.
Sofern angegeben, können Entwickler mithilfe der Quelleinträge genau nachvollziehen, wie jedes Skript im langen Animationsframe bis zur Zeichenposition im aufrufenden Skript aufgerufen wurde. Hier sehen Sie den genauen Speicherort in einer JavaScript-Ressource, der zu dem langen Animationsframe geführt hat.
Beispiel für einen long-animation-frame
-Leistungseintrag
Hier ein vollständiges Beispiel für einen long-animation-frame
-Leistungseintrag mit einem einzelnen 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
}
Wie Sie sehen, erhalten Sie so eine nie dagewesene Menge an Daten, mit denen Sie die Ursache für verzögerte Rendering-Aktualisierungen ermitteln können.
Long Animation Frames API im Feld verwenden
Tools wie die Chrome-Entwicklertools und Lighthouse sind zwar nützlich, um Probleme zu erkennen und zu reproduzieren, aber sie sind Lab-Tools, die wichtige Aspekte der Nutzererfahrung übersehen können, die nur Felddaten liefern können.
Die Long Animation Frames API wurde entwickelt, um wichtige Kontextdaten für Nutzerinteraktionen zu erfassen, die mit der Long Tasks API nicht möglich sind. So können Sie Probleme bei der Interaktivität identifizieren und reproduzieren, die Ihnen sonst möglicherweise nicht aufgefallen wären.
Unterstützung der API für die Funktion zur Erkennung langer Frames bei Animationen
Mit dem folgenden Code kannst du testen, ob die API unterstützt wird:
if (PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')) {
// Monitor LoAFs
}
Link zur längsten INP-Interaktion
Der offensichtlichste Anwendungsfall für die Long Animation Frames API besteht darin, Probleme mit der Interaktion bis zur nächsten Darstellung (Interaction to Next Paint, INP) zu diagnostizieren und zu beheben. Dies war einer der Hauptgründe, warum das Chrome-Team diese API entwickelt hat. Bei einem guten INP werden alle Interaktionen innerhalb von 200 Millisekunden nach der Interaktion bis zur Darstellung des Frames verarbeitet. Da die Long Animation Frames API alle Frames misst, die mindestens 50 Millisekunden dauern, sollten die meisten problematischen INPs LoAF-Daten enthalten, damit Sie diese Interaktionen diagnostizieren können.
Die „INP LoAF“ ist das LoAF, das die INP-Interaktion enthält, wie im folgenden Diagramm dargestellt:
In einigen Fällen ist es möglich, dass ein INP-Ereignis zwei LoAFs umfasst. Dies geschieht normalerweise, wenn die Interaktion erfolgt, nachdem der Frame das Rendering des vorherigen Frames gestartet hat und der Event-Handler im nächsten Frame verarbeitet wird:
In seltenen Fällen kann es sogar mehr als zwei LoAFs umfassen.
Wenn Sie die Daten der LoAFs erfassen, die mit der INP-Interaktion verknüpft sind, erhalten Sie viel mehr Informationen zur INP-Interaktion, die Ihnen bei der Diagnose helfen. Das ist besonders hilfreich, um die Eingabeverzögerung zu verstehen, da Sie sehen können, welche anderen Scripts in diesem Frame ausgeführt wurden.
Es kann auch hilfreich sein, die unerklärlichen Verarbeitungsdauer und Verzögerungen bei der Präsentation zu verstehen, wenn Ihre Event-Handler die für diese erfassten Werte nicht reproduzieren, da möglicherweise andere Skripts für Ihre Nutzer ausgeführt werden, die möglicherweise nicht in Ihren eigenen Tests enthalten sind.
Es gibt keine direkte API, um einen INP-Eintrag mit den zugehörigen LoAF-Einträgen zu verknüpfen. Es ist jedoch möglich, dies im Code zu tun, indem die Start- und Endzeiten der einzelnen Einträge verglichen werden (siehe Beispielscript für WhyNp). Die web-vitals
-Bibliothek enthält alle sich überschneidenden LoAFs in der longAnimationFramesEntries
-Property der INP-Attributionsoberfläche ab Version 4.
Nachdem Sie den oder die LoAF-Einträge verknüpft haben, können Sie Informationen mit der INP-Zuordnung hinzufügen. Das scripts
-Objekt enthält einige der wertvollsten Informationen, da es zeigen kann, was sonst in diesen Frames lief. Durch das Beaconing dieser Daten an Ihren Analysedienst können Sie also besser nachvollziehen, warum Interaktionen langsam waren.
Wenn Sie LoAFs für die INP-Interaktion melden, können Sie die dringendsten Interaktivitätsprobleme auf Ihrer Seite ermitteln. Jeder Nutzer kann unterschiedlich mit Ihrer Seite interagieren. Bei ausreichender Datenmenge für die Attribution über indirekte Zugriffe sind einige potenzielle Probleme in den Daten enthalten. So können Sie Scripts nach Volumen sortieren, um zu sehen, welche Scripts mit einer langsamen INP korrelieren.
Längere Animationsdaten an einen Analyseendpunkt zurückgeben
Ein Nachteil der ausschließlichen Betrachtung der INP-LoAFs besteht darin, dass Sie möglicherweise andere potenzielle Verbesserungsmöglichkeiten übersehen, die zu zukünftigen INP-Problemen führen können. Das kann dazu führen, dass Sie das Gefühl haben, im Kreis zu laufen, wenn Sie ein INP-Problem beheben und eine große Verbesserung erwarten, nur um festzustellen, dass die nächste langsamste Interaktion nur geringfügig besser ist, sodass sich Ihr INP nicht wesentlich verbessert.
Anstatt sich nur auf den INP-LoAF zu konzentrieren, sollten Sie alle LoAFs über die gesamte Lebensdauer der Seite hinweg berücksichtigen:
Jeder LoAF-Eintrag enthält jedoch erhebliche Daten. Daher sollten Sie Ihre Analyse wahrscheinlich auf einige LoAFs beschränken. Da die Einträge für lange Animationsframes außerdem recht groß sein können, sollten Entwickler entscheiden, welche Daten aus dem Eintrag an Analytics gesendet werden sollen. Dazu gehören beispielsweise die Zusammenfassungszeiten des Eintrags und möglicherweise die Scriptnamen oder andere Mindestmengen an anderen Kontextdaten, die als erforderlich erachtet werden.
Hier einige Vorschläge, wie Sie die Menge der Daten für lange Animationsframes reduzieren können:
- Lange Animationsframes mit Interaktionen beobachten
- Achten Sie auf lange Frames mit hoher Blockierungsdauer.
- Während kritischer UI-Aktualisierungen lange Animationsframes beobachten, um die Flüssigkeit zu verbessern
- Die schlechtesten langen Animationsframes beobachten
- Gängige Muster in langen Animationsframes erkennen
Welches dieser Muster am besten für Sie geeignet ist, hängt davon ab, wie weit Sie mit der Optimierung fortgeschritten sind und wie häufig lange Animationsframes vorkommen. Bei einer Website, die noch nie für die Responsivität optimiert wurde, kann es viele LoAFs geben. Sie können sich auf LoAFs mit Interaktionen beschränken, einen hohen Grenzwert festlegen oder sich nur die schlechtesten ansehen.
Wenn Sie die häufigsten Probleme mit der Reaktionsfähigkeit behoben haben, können Sie die Funktion erweitern, indem Sie sie nicht nur auf Interaktionen oder lange Blockierungsdauern beschränken oder die Grenzwerte senken.
Lange Animationsframes mit Interaktionen beobachten
Um Informationen über den INP-Frame für lange Animationen hinaus zu erhalten, können Sie sich alle LoAFs mit Interaktionen (die durch das Vorhandensein eines firstUIEventTimestamp
-Werts erkannt werden) mit einem hohen blockingDuration
ansehen.
Dies kann auch eine einfachere Methode zur Überwachung der INP-LoAFs sein, anstatt zu versuchen, die beiden zu korrelieren, was komplexer sein kann. In den meisten Fällen ist dies die LoAF für die Interaktion mit dem INP für einen bestimmten Besuch. In seltenen Fällen, in denen dies nicht der Fall ist, werden trotzdem lange Interaktionen angezeigt, die behoben werden müssen, da sie möglicherweise die Interaktion mit dem INP für andere Nutzer ist.
Der folgende Code protokolliert alle LoAF-Einträge mit einer blockingDuration
von mehr als 100 Millisekunden, bei denen während des Frames eine Interaktion stattgefunden hat. Die 100 wird hier ausgewählt, da sie unter dem INP-Grenzwert von 200 Millisekunden liegt. Je nach Bedarf können Sie einen höheren oder niedrigeren Wert auswählen.
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 });
Lange Animationsframes mit hoher Blockierungsdauer beobachten
Anstatt sich alle langen Frames mit Interaktionen anzusehen, sollten Sie sich alle langen Frames mit langen Blockierungsdauern ansehen. Diese geben Aufschluss über potenzielle INP-Probleme, wenn ein Nutzer während dieser langen Animationsframes interagiert.
Mit dem folgenden Code werden alle LoAF-Einträge mit einer Blockierdauer von mehr als 100 Millisekunden protokolliert, bei denen während des Frames eine Interaktion stattfand. Die Zahl 100 wird hier ausgewählt, da sie unter dem INP-Grenzwert von 200 Millisekunden liegt, um potenzielle Problemframes zu identifizieren und gleichzeitig die Anzahl der gemeldeten langen Animationsframes auf ein Minimum zu beschränken. Sie können je nach Ihren Anforderungen einen höheren oder niedrigeren Wert wählen.
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 });
Lange Animationsframes bei wichtigen UI-Änderungen beobachten, um die Laufruhe zu verbessern
Wie bereits erwähnt, kann die Prüfung langer Frames mit hoher Blockierungsdauer dazu beitragen, die Eingabereaktion zu verbessern. Für eine flüssige Animation sollten Sie sich jedoch alle langen Animationsframes mit einer langen duration
ansehen.
Da dies zu sehr ungenauen Ergebnissen führen kann, sollten Sie die Messungen auf wichtige Punkte mit einem Muster wie diesem beschränken:
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;
}
Die schlechtesten Long-Animation-Frames beobachten
Anstatt einen Grenzwert festzulegen, können Websites Daten für den längsten Animationsframe (oder Frames) erfassen, um das Volumen der Daten zu reduzieren, die per Beacon gesendet werden müssen. Unabhängig davon, wie viele lange Animationsframes auf einer Seite vorhanden sind, werden nur Daten für die fünf, zehn oder wie viele langen Animationsframes auch immer absolut notwendig sind, zurückgesendet.
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 });
Diese Strategien können auch kombiniert werden. Sehen Sie sich nur die zehn schlechtesten LoAFs mit Interaktionen an, die länger als 100 Millisekunden dauern.
Senden Sie das Beacon zum richtigen Zeitpunkt (idealerweise beim visibilitychange
-Ereignis) zurück an Analytics. Für lokale Tests können Sie console.table
regelmäßig verwenden:
console.table(longestBlockingLoAFs);
Gängige Muster in langen Animationsframes identifizieren
Eine alternative Strategie wäre, sich gängige Scripts anzusehen, die am häufigsten in langen Animationsframe-Einträgen vorkommen. Daten können auf Skript- und Zeichenpositionsebene gemeldet werden, um Wiederholungstäter zu identifizieren.
Das funktioniert möglicherweise besonders gut für anpassbare Plattformen, auf denen Themen oder Plug-ins, die Leistungsprobleme verursachen, auf einer Reihe von Websites identifiziert werden können.
Die Ausführungszeit gängiger Scripts oder Drittanbieter-Quellen in langen Animationsframes kann summiert und zurückgemeldet werden, um häufige Ursachen für lange Animationsframes auf einer Website oder einer Gruppe von Websites zu identifizieren. So können Sie sich beispielsweise URLs ansehen:
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});
Ein Beispiel für diese Ausgabe:
(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 |
Long Animation Frames API in Tools verwenden
Die API bietet auch zusätzliche Entwicklertools für das lokale Debugging. Mit einigen Tools wie Lighthouse und den Chrome-Entwicklertools konnten zwar viele dieser Daten mit Low-Level-Tracing-Details erhoben werden, aber mit dieser übergeordneten API könnten andere Tools auf diese Daten zugreifen.
Daten zu langen Animationsframes in den Entwicklertools ansehen
Mit der performance.measure()
API können Sie lange Animationsframes in den DevTools anzeigen lassen. Diese werden dann in Leistungsaufzeichnungen im DevTools-Nutzerzeit-Track angezeigt, um zu zeigen, wo Sie sich auf Leistungsverbesserungen konzentrieren sollten. Mit der DevTools Extensibility API können diese sogar in einem eigenen Track angezeigt werden:
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 });
Langfristig werden lange Animationsframes wahrscheinlich in die DevTools selbst eingebunden. Mit dem vorherigen Code-Snippet können sie aber in der Zwischenzeit dort angezeigt werden.
Der erste Eintrag in der vorherigen Abbildung zeigt ebenfalls, wo der Browser mehrere Aufgaben zusammen im selben langen Animationsframe verarbeitet hat, anstatt zwischen ihnen zu rendern. Wie bereits erwähnt, kann dies passieren, wenn es keine Eingabeaufgaben mit hoher Priorität, aber eine Warteschlange mit Aufgaben gibt. Für die erste lange Aufgabe müssen einige Rendering-Aktualisierungen ausgeführt werden (andernfalls wird der aktuelle lange Animationsframe im Anschluss zurückgesetzt und mit der nächsten Aufgabe ein neuer gestartet). Statt sofort zu rendern, hat der Browser eine Reihe zusätzlicher Aufgaben verarbeitet, erst dann die lange Rendering-Aufgabe ausgeführt und den langen Animationsframe beendet. Das zeigt, wie nützlich es ist, sich in den DevTools lange Animationsframes anzusehen, anstatt nur lange Aufgaben, um verzögerte Renderings zu identifizieren.
Daten zu langen Animationsframes in anderen Entwicklertools verwenden
Die Web Vitals-Erweiterung hat den Wert in den Debug-Informationen der Zusammenfassungszusammenfassung angezeigt, um Leistungsprobleme zu diagnostizieren.
Außerdem werden jetzt Daten zu langen Animationsframes für jeden INP-Callback und jede Interaktion angezeigt:
Daten zu langen Animationsframes in automatisierten Testtools verwenden
Ähnlich können automatisierte Testtools in CI/CD-Pipelines Details zu potenziellen Leistungsproblemen aufzeigen, indem lange Animationsframes während der Ausführung verschiedener Test-Suites gemessen werden.
FAQ
Zu den häufig gestellten Fragen zu dieser API gehören:
Warum nicht einfach die Long Tasks API erweitern oder iterieren?
Dies ist eine alternative Möglichkeit, eine ähnliche, aber letztendlich andere Messung potenzieller Probleme mit der Reaktionsfähigkeit zu erfassen. Es ist wichtig, dass Websites, die auf die bestehende Long Tasks API angewiesen sind, weiterhin funktionieren, um Unterbrechungen bestehender Anwendungsfälle zu vermeiden.
Die Long Tasks API kann zwar von einigen der Funktionen von LoAF profitieren (z. B. einem besseren Attributionsmodell), wir sind jedoch der Meinung, dass der Fokus auf Frames statt auf Aufgaben viele Vorteile bietet, die diese API grundlegend von der bestehenden Long Tasks API unterscheiden.
Why do I not have script entries?
Dies kann darauf hindeuten, dass der lange Animationsframe nicht auf JavaScript, sondern auf eine große Menge an Rendering zurückzuführen ist.
Das kann auch passieren, wenn der lange Animationsframe auf JavaScript zurückzuführen ist, die Script-Attribution aber aus verschiedenen Datenschutzgründen, wie bereits erwähnt, nicht angegeben werden kann (vor allem, wenn das JavaScript nicht der Seite gehört).
Warum habe ich Scripteinträge, aber keine oder nur wenige Quelleninformationen?
Das kann verschiedene Gründe haben, z. B. dass keine gute Quelle angegeben wurde.
Für no-cors cross-origin
-Scripts sind ebenfalls nur begrenzte Skriptinformationen verfügbar. Das Problem lässt sich jedoch beheben, indem Sie diese Scripts mit CORS abrufen. Fügen Sie dazu dem <script>
-Aufruf crossOrigin = "anonymous"
hinzu.
Hier sehen Sie beispielsweise das standardmäßige Google Tag Manager-Skript, das Sie der Seite hinzufügen möchten:
<!-- 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 -->
Kann durch Hinzufügen von j.crossOrigin = "anonymous"
erweitert werden, um vollständige Attributionsdetails für GTM bereitzustellen
Wird die Long Tasks API dadurch ersetzt?
Wir sind der Meinung, dass die Long Animation Frames API eine bessere, umfassendere API für die Messung langer Aufgaben ist. Derzeit ist jedoch nicht geplant, die Long Tasks API einzustellen.
Feedback erwünscht
Feedback können Sie über die GitHub-Problemliste geben. Fehler bei der Implementierung der API in Chrome können Sie über die Problemverfolgung von Chrome melden.
Fazit
Die Long Animation Frames API ist eine spannende neue API mit vielen potenziellen Vorteilen gegenüber der vorherigen Long Tasks API.
Es erweist sich als wichtiges Tool zur Behebung von Problemen mit der Reaktionsfähigkeit, gemessen am INP. Der Messwert „INP“ lässt sich nur schwer optimieren. Mit dieser API möchte das Chrome-Team Entwicklern die Identifizierung und Behebung von Problemen erleichtern.
Der Umfang der Long Animation Frames API geht jedoch über INP hinaus und kann helfen, andere Ursachen für langsame Aktualisierungen zu identifizieren, die sich auf die allgemeine Nutzerfreundlichkeit einer Website auswirken können.