Signatur
Beschreibung
PerformanceResourceTiming ist ein spezieller PerformanceEntry mit dem entryType "resource". Der Browser legt automatisch für jede geladene Ressource einen solchen Eintrag an, etwa für Bilder, Skripte, Stylesheets, Schriften, fetch()- und XMLHttpRequest-Anfragen oder iframes. Die Eigenschaft name enthält die URL der Ressource, initiatorType sagt, wodurch sie geladen wurde (z. B. "img", "script", "fetch", "css").
Die Zeitstempel sind hochauflösende DOMHighResTimeStamp-Werte in Millisekunden, gemessen relativ zu performance.timeOrigin. Sie folgen dem Ablauf einer Anfrage: startTime → redirectStart/redirectEnd → workerStart → fetchStart → domainLookupStart/domainLookupEnd (DNS) → connectStart/secureConnectionStart/connectEnd (TCP/TLS) → requestStart → responseStart (erstes Byte, TTFB) → responseEnd. Aus den Differenzen berechnet man z. B. DNS-Dauer, Verbindungsaufbau oder Übertragungszeit. duration entspricht responseEnd - startTime.
Dazu kommen Größenangaben: transferSize (übertragene Bytes inkl. Header, 0 bei Cache-Treffer), encodedBodySize (komprimierter Body) und decodedBodySize (entpackter Body). Neuere Browser bieten außerdem nextHopProtocol (z. B. "h2", "h3"), renderBlockingStatus, responseStatus und serverTiming (ein Array von PerformanceServerTiming-Objekten aus dem Server-Timing-Header).
Einträge liest man über performance.getEntriesByType("resource") aus oder, besser, über einen PerformanceObserver mit type: "resource" und buffered: true. So erfasst man auch Ressourcen, die später nachgeladen werden. Typische Einsätze sind Real User Monitoring (RUM), das Finden langsamer Drittanbieter-Skripte, das Prüfen der Cache-Trefferquote und das Überwachen von API-Latenzen.
Rückgabewert
performance.getEntriesByType("resource"), performance.getEntriesByName(url) oder ein PerformanceObserver. Die Methode toJSON() gibt ein einfaches Objekt mit allen Eigenschaften zurück.Beispiele
Alle geladenen Ressourcen mit Dauer auflisten
const resources = performance.getEntriesByType('resource');
for (const entry of resources) {
console.log(
`${entry.initiatorType.padEnd(8)} ${entry.duration.toFixed(1).padStart(7)} ms ${entry.name}`
);
}
Netzwerkphasen einer Ressource aufschlüsseln
const phasesOf = (e) => ({
url: e.name,
redirect: e.redirectEnd - e.redirectStart,
dns: e.domainLookupEnd - e.domainLookupStart,
tcp: e.connectEnd - e.connectStart,
tls: e.secureConnectionStart > 0 ? e.connectEnd - e.secureConnectionStart : 0,
ttfb: e.responseStart - e.requestStart,
download: e.responseEnd - e.responseStart,
protocol: e.nextHopProtocol,
fromCache: e.transferSize === 0 && e.decodedBodySize > 0
});
const [entry] = performance.getEntriesByName(new URL('/app.js', location.href).href);
if (entry) console.table(phasesOf(entry));
Langsame API-Aufrufe per PerformanceObserver melden
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.initiatorType === 'fetch' && entry.duration > 500) {
navigator.sendBeacon('/rum', JSON.stringify({
url: entry.name,
duration: Math.round(entry.duration),
status: entry.responseStatus,
serverTiming: entry.serverTiming?.map(({ name, duration }) => ({ name, duration }))
}));
}
}
});
// buffered: true liefert auch bereits vorhandene Einträge
observer.observe({ type: 'resource', buffered: true });
Puffergröße erhöhen und Überlauf behandeln
performance.setResourceTimingBufferSize(500);
performance.addEventListener('resourcetimingbufferfull', () => {
const entries = performance.getEntriesByType('resource');
console.log(`Puffer voll – sichere ${entries.length} Einträge`);
// Einträge auswerten/versenden, danach Puffer leeren
performance.clearResourceTimings();
});
// Wichtig · Fallstricke
- Cross-Origin-Einschränkung: Bei Ressourcen von fremden Ursprüngen sind die meisten Detailwerte (
domainLookupStart,connectStart,requestStart,responseStart,transferSize,encodedBodySize,decodedBodySize,serverTiming…) auf0gesetzt bzw. leer. Nur wenn der Server den HeaderTiming-Allow-Origin: *(oder Ihren Ursprung) sendet, sind sie sichtbar.startTime,durationundresponseEndsind immer verfügbar. - Nullwerte richtig deuten:
redirectStart,secureConnectionStartundworkerStartsind0, wenn keine Weiterleitung, kein TLS bzw. kein Service Worker beteiligt war. Bei wiederverwendeten Verbindungen sind DNS- und TCP-Phase0ms lang. Vor dem Rechnen immer auf> 0prüfen. - Puffergrenze: Der Standardpuffer fasst oft nur 250 Einträge. Danach werden keine neuen Einträge mehr in
getEntriesByType()aufgenommen, und es feuertresourcetimingbufferfull. EinPerformanceObservererhält neue Einträge trotzdem, deshalb ist er für langlebige Single-Page-Apps die bessere Wahl. - Zeitpunkt: Ein Eintrag entsteht erst, wenn die Ressource fertig geladen ist. Abgebrochene oder fehlgeschlagene Anfragen erscheinen je nach Browser gar nicht.
- Kompatibilität: Die Grundeigenschaften werden überall unterstützt.
responseStatus,renderBlockingStatus,deliveryTypeundcontentTypesind neuer und fehlen teilweise in Safari/Firefox. Deshalb vor der Nutzung prüfen, etwa mit'responseStatus' in entry. - Datenschutz: Zeitstempel werden aus Sicherheitsgründen (Spectre) gerundet. Ohne Cross-Origin-Isolation ist die Auflösung gröber, meist 100 µs bis 1 ms.