Signatur
Beschreibung
Die schreibgeschützte Eigenschaft renderStart gehört zur Long Animation Frames API (LoAF). Sie gibt den Zeitpunkt an, an dem der Browser innerhalb eines langen Animation-Frames (Eintragstyp "long-animation-frame", Dauer über 50 ms) mit dem Rendering-Zyklus begonnen hat. Der Wert ist relativ zu performance.timeOrigin, genau wie startTime.
Zum Rendering-Zyklus zählen die requestAnimationFrame()-Callbacks, die Berechnung von Stilen und Layout sowie die Callbacks von ResizeObserver und IntersectionObserver. Zusammen mit styleAndLayoutStart, startTime und duration lässt sich ein langer Frame in einzelne Phasen zerlegen:
- Skript-/Task-Phase:
renderStart - startTime - rAF-Callbacks:
styleAndLayoutStart - renderStart - Stil & Layout (inkl. Observer):
startTime + duration - styleAndLayoutStart - Gesamte Rendering-Phase:
startTime + duration - renderStart
Das hilft bei der Frage, ob eine träge Interaktion (schlechter INP-Wert) durch langes JavaScript in Event-Handlern oder durch teures Rendering, etwa aufwendige rAF-Callbacks oder erzwungenes Layout, verursacht wurde.
Rückgabewert
performance.timeOrigin, an dem der Rendering-Zyklus begann. Hat der Frame nicht gerendert (z. B. nur ein langer Task ohne sichtbare Aktualisierung), ist der Wert 0.Beispiele
renderStart langer Frames beobachten
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(
`LoAF: Start ${entry.startTime.toFixed(1)} ms, ` +
`Render-Start ${entry.renderStart.toFixed(1)} ms, ` +
`Dauer ${entry.duration.toFixed(1)} ms`
);
}
});
// buffered: true liefert auch bereits aufgezeichnete Einträge
observer.observe({ type: 'long-animation-frame', buffered: true });
Langen Frame in Phasen zerlegen
const analyzeFrame = (entry) => {
const end = entry.startTime + entry.duration;
// Kein Rendering in diesem Frame
if (entry.renderStart === 0) {
return { script: entry.duration, raf: 0, styleLayout: 0 };
}
return {
script: entry.renderStart - entry.startTime,
raf: entry.styleAndLayoutStart - entry.renderStart,
styleLayout: end - entry.styleAndLayoutStart
};
};
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
const phases = analyzeFrame(entry);
console.table(
Object.fromEntries(
Object.entries(phases).map(([k, v]) => [k, `${v.toFixed(1)} ms`])
)
);
}
}).observe({ type: 'long-animation-frame', buffered: true });
Rendering-lastige Frames an Analytics melden (mit Feature-Erkennung)
const supportsLoAF =
PerformanceObserver.supportedEntryTypes?.includes('long-animation-frame');
if (supportsLoAF) {
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.renderStart === 0) continue;
const renderTime = entry.startTime + entry.duration - entry.renderStart;
// Nur melden, wenn das Rendering den Großteil des Frames ausmacht
if (renderTime > entry.duration / 2) {
navigator.sendBeacon('/analytics/loaf', JSON.stringify({
renderTime: Math.round(renderTime),
duration: Math.round(entry.duration),
url: location.pathname
}));
}
}
}).observe({ type: 'long-animation-frame', buffered: true });
} else {
console.info('Long Animation Frames API wird nicht unterstützt.');
}
// Wichtig · Fallstricke
- Wert 0: Wenn in einem langen Frame nichts gerendert wurde, ist
renderStartgleich0. Prüfen Sie das immer vor Differenzberechnungen, sonst erhalten Sie unsinnige negative oder riesige Werte. - Browser-Unterstützung: Die API gibt es nur in Chromium-basierten Browsern (Chrome/Edge ab 123). Firefox und Safari unterstützen sie nicht. Prüfen Sie die Unterstützung vorher mit
PerformanceObserver.supportedEntryTypes.includes('long-animation-frame'). - Nur lange Frames: Einträge entstehen erst ab einer Frame-Dauer von über 50 ms. Kurze Frames erscheinen nicht und lassen sich darüber nicht messen.
- Genauigkeit: Aus Datenschutzgründen (Schutz vor Timing-Angriffen) runden Browser die Zeitstempel ab. Ohne Cross-Origin-Isolation ist die Auflösung gröber.
- Nicht über
getEntriesByType(): Die Einträge bekommen Sie zuverlässig nur perPerformanceObserver. Mitbuffered: trueerhalten Sie auch Einträge, die vor der Registrierung aufgezeichnet wurden.