Start · Sprachen · JavaScript · Referenz · PerformanceResourceTiming

PerformanceResourceTiming

Schnittstelle

Liefert detaillierte Netzwerk-Zeitmessungen (DNS, TCP, TLS, Anfrage, Antwort) und Größenangaben für jede Ressource, die eine Seite lädt.

seit JavaScript Baseline: alle modernen Browser (Resource Timing L Kategorie: webapi

Signatur

interface PerformanceResourceTiming extends PerformanceEntry

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

Typ
PerformanceResourceTiming
Beschreibung
Wird nicht selbst erzeugt (kein öffentlicher Konstruktor). Instanzen liefern 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}`
  );
}
script 84.3 ms https://example.com/app.js img 42.1 ms https://example.com/logo.png fetch 120.7 ms https://example.com/api/user

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));
{ url: 'https://example.com/app.js', redirect: 0, dns: 12.4, tcp: 18.9, tls: 11.2, ttfb: 35.6, download: 6.1, protocol: 'h2', fromCache: false }

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();
});
Puffer voll – sichere 500 Einträge

// Wichtig · Fallstricke

  • Cross-Origin-Einschränkung: Bei Ressourcen von fremden Ursprüngen sind die meisten Detailwerte (domainLookupStart, connectStart, requestStart, responseStart, transferSize, encodedBodySize, decodedBodySize, serverTiming …) auf 0 gesetzt bzw. leer. Nur wenn der Server den Header Timing-Allow-Origin: * (oder Ihren Ursprung) sendet, sind sie sichtbar. startTime, duration und responseEnd sind immer verfügbar.
  • Nullwerte richtig deuten: redirectStart, secureConnectionStart und workerStart sind 0, wenn keine Weiterleitung, kein TLS bzw. kein Service Worker beteiligt war. Bei wiederverwendeten Verbindungen sind DNS- und TCP-Phase 0 ms lang. Vor dem Rechnen immer auf > 0 prüfen.
  • Puffergrenze: Der Standardpuffer fasst oft nur 250 Einträge. Danach werden keine neuen Einträge mehr in getEntriesByType() aufgenommen, und es feuert resourcetimingbufferfull. Ein PerformanceObserver erhä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, deliveryType und contentType sind 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.