Signatur
Beschreibung
Die Eigenschaft loadTime eines LargestContentfulPaint-Eintrags gibt den Zeitpunkt in Millisekunden relativ zu performance.timeOrigin an, zu dem die Ressource des größten sichtbaren Inhaltselements (z. B. ein <img>, ein Posterbild eines <video> oder ein CSS-Hintergrundbild) vollständig geladen war.
Zusammen mit renderTime und startTime lässt sich damit der LCP-Wert genauer aufschlüsseln: Die Differenz zwischen renderTime und loadTime zeigt die Render-Verzögerung, also wie lange ein bereits geladenes Bild auf das Zeichnen gewartet hat (z. B. wegen blockierendem JavaScript oder CSS). Die Differenz zwischen loadTime und dem Beginn der Anfrage (aus PerformanceResourceTiming) zeigt die reine Ladedauer.
Bei reinen Textelementen gibt es keine zu ladende Ressource – loadTime ist dann 0. Man liest die Eigenschaft typischerweise in einem PerformanceObserver mit dem Eintragstyp "largest-contentful-paint" und der Option buffered: true aus.
Rückgabewert
performance.timeOrigin; 0, wenn das Element keine Ressource lädt (z. B. Textblock).Beispiele
loadTime des LCP-Elements protokollieren
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
const lcp = entries[entries.length - 1];
console.log('LCP-Element:', lcp.element);
console.log('Geladen nach', Math.round(lcp.loadTime), 'ms');
});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
Render-Verzögerung berechnen
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.loadTime === 0) {
console.log('Textelement – keine Ressource geladen');
continue;
}
// renderTime kann bei Cross-Origin-Bildern ohne Timing-Allow-Origin 0 sein
const render = entry.renderTime || entry.startTime;
const delay = render - entry.loadTime;
console.log(`Render-Verzögerung: ${delay.toFixed(1)} ms (${entry.url})`);
}
}).observe({ type: 'largest-contentful-paint', buffered: true });
LCP-Phasen für Monitoring aufschlüsseln
new PerformanceObserver((list) => {
const lcp = list.getEntries().at(-1);
const [nav] = performance.getEntriesByType('navigation');
const res = lcp.url
? performance.getEntriesByName(lcp.url, 'resource')[0]
: null;
const ttfb = nav.responseStart;
const loadStart = res ? res.requestStart || res.startTime : ttfb;
const phases = {
ttfb,
ladeverzoegerung: Math.max(0, loadStart - ttfb),
ladedauer: lcp.loadTime ? lcp.loadTime - loadStart : 0,
renderverzoegerung: lcp.startTime - Math.max(lcp.loadTime, ttfb)
};
console.table(phases);
navigator.sendBeacon('/rum', JSON.stringify(phases));
}).observe({ type: 'largest-contentful-paint', buffered: true });
// Wichtig · Fallstricke
- Textelemente:
loadTimeist0, da keine Ressource geladen wird – vor Berechnungen immer prüfen. - Cross-Origin-Bilder:
loadTimesteht zwar zur Verfügung,renderTimewird aber ohneTiming-Allow-Origin-Header ggf. auf0gesetzt bzw. vergröbert. Für Differenzen daher aufstartTimeausweichen. - Mehrere Einträge: Während des Ladens können mehrere LCP-Einträge entstehen; maßgeblich ist der letzte vor der ersten Nutzerinteraktion.
- Kompatibilität: Chromium-Browser seit Version 77, Firefox seit 122, Safari erst sehr neu – vor Nutzung mit
PerformanceObserver.supportedEntryTypes.includes('largest-contentful-paint')prüfen. - Einträge in Hintergrund-Tabs sind unzuverlässig; Messungen ggf. verwerfen, wenn
document.visibilityStatevorher"hidden"war.