Navigations- und Ressourcen-Timings
Navigations-Timings sind Metriken zur Messung der Navigationsereignisse eines Browsers. Ressourcen-Timings sind detaillierte Netzwerk-Timing-Messungen zum Laden von Ressourcen einer Anwendung. Beide bieten dieselben schreibgeschützten Eigenschaften, aber die Navigations-Timing misst die Zeitmessungen des Hauptdokuments, während die Ressourcen-Timing die Zeiten für alle vom Hauptdokument aufgerufenen Ressourcen und die angeforderten Ressourcen der Ressourcen bereitstellt.
Die generellen Performance-Timings unten wurden zugunsten der Performance Entry API, die es ermöglicht, entlang des Navigations- und Ressourcenladeprozesses Zeiten zu markieren und zu messen, als veraltet markiert. Obwohl veraltet, werden sie in allen Browsern unterstützt.
Performance Timings
Die performanceTiming API, eine JavaScript-API zur Messung der Ladeperformance der angeforderten Seite, ist veraltet, wird jedoch in allen Browsern unterstützt. Sie wurde durch die performanceNavigationTiming API ersetzt.
Die Performance-Timing-API bot schreibgeschützte Zeiten in Millisekunden(ms), die beschreiben, wann jeder Punkt im Seitenladeprozess erreicht wurde. Wie im Bild unten gezeigt, geht der Navigationsprozess von navigationStart, unloadEventStart, unloadEventEnd, redirectStart, redirectEnd, fetchStart, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, responseStart, responseEnd, domLoading, domInteractive, domContentLoadedEventStart, domContentLoadedEventEnd, domComplete, loadEventStart und loadEventEnd.

Mit den obigen Metriken und etwas Mathematik können wir viele wichtige Metriken berechnen, wie Time to First Byte, Seitenladezeit, DNS-Abfrage und ob die Verbindung sicher ist.
Um den Zeitaufwand für alle Schritte zu messen, bietet die Performance-Timing-API schreibgeschützte Messungen der Navigations-Timings. Um unsere App-Timings zu betrachten und zu erfassen, geben wir ein:
let time = window.performance.timing;
Wir können dann die Ergebnisse nutzen, um zu messen, wie gut unsere App funktioniert.

Die Reihenfolge ist:
| Performance Timings | Details |
|---|---|
| [`navigationStart`](/de/docs/Web/API/PerformanceTiming/navigationStart) |
Wenn die Aufforderung zum Entladen des vorherigen Dokuments im selben
Browsing-Kontext endet. Wenn es kein vorheriges Dokument gibt, wird
dieser Wert derselbe sein wie PerformanceTiming.fetchStart.
|
| [`secureConnectionStart`](/de/docs/Web/API/PerformanceTiming/secureConnectionStart) |
Wenn der sichere Verbindungs-Handshake beginnt. Wenn keine solche
Verbindung angefordert wird, wird 0 zurückgegeben.
|
| [`redirectStart`](/de/docs/Web/API/PerformanceTiming/redirectStart) |
Wenn die erste HTTP-Weiterleitung beginnt. Wenn es keine Weiterleitung
gibt oder eine der Weiterleitungen nicht vom selben Ursprung stammt,
ist der zurückgegebene Wert 0.
|
| [`redirectEnd`](/de/docs/Web/API/PerformanceTiming/redirectEnd) |
Wenn die letzte HTTP-Weiterleitung abgeschlossen ist, also wenn das
letzte Byte der HTTP-Antwort empfangen wurde. Wenn es keine
Weiterleitung gibt oder eine der Weiterleitungen nicht vom selben
Ursprung stammt, ist der zurückgegebene Wert |
| [`connectEnd`](/de/docs/Web/API/PerformanceTiming/connectEnd) |
Wenn die Netzwerkverbindung geöffnet ist. Wenn die Transportschicht
einen Fehler meldet und die Verbindung erneut gestartet wird, wird die
Endzeit der letzten Verbindungsherstellung angegeben. Wenn eine
persistente Verbindung verwendet wird, ist der Wert derselbe wie
PerformanceTiming.fetchStart. Eine Verbindung gilt als
geöffnet, wenn alle sicheren Verbindungs-Handshakes oder
SOCKS-Authentifizierungen beendet sind.
|
| [`connectStart`](/de/docs/Web/API/PerformanceTiming/connectStart) |
Wenn die Anfrage zum Öffnen einer Verbindung an das Netzwerk gesendet
wird. Wenn die Transportschicht einen Fehler meldet und die Verbindung
erneut gestartet wird, wird die Startzeit der letzten
Verbindungsherstellung angegeben. Wenn eine persistente Verbindung
verwendet wird, ist der Wert derselbe wie
PerformanceTiming.fetchStart.
|
| [`domainLookupEnd`](/de/docs/Web/API/PerformanceTiming/domainLookupEnd) |
Wenn die Domain-Abfrage abgeschlossen ist. Wenn eine persistente
Verbindung verwendet wird oder die Information im Cache oder einer
lokalen Ressource gespeichert ist, ist der Wert derselbe wie
PerformanceTiming.fetchStart.
|
| [`domainLookupStart`](/de/docs/Web/API/PerformanceTiming/domainLookupStart) |
Wenn die Domain-Abfrage beginnt. Wenn eine persistente Verbindung
verwendet wird oder die Information im Cache oder einer lokalen
Ressource gespeichert ist, ist der Wert derselbe wie
PerformanceTiming.fetchStart.
|
| [`fetchStart`](/de/docs/Web/API/PerformanceTiming/fetchStart) | Wenn der Browser bereit ist, das Dokument mit einer HTTP-Anfrage abzurufen. Dieser Moment liegt vor der Überprüfung eines Anwendungs-Caches. |
| [`requestStart`](/de/docs/Web/API/PerformanceTiming/requestStart) | Wenn der Browser die Anfrage gesendet hat, um das aktuelle Dokument vom Server oder aus einem Cache zu erhalten. Wenn die Transportschicht nach Beginn der Anfrage fehlschlägt und die Verbindung erneut geöffnet wird, wird diese Eigenschaft auf die Zeit der neuen Anfrage gesetzt. |
| [`responseStart`](/de/docs/Web/API/PerformanceTiming/responseStart) | Wenn der Browser das erste Byte der Antwort vom Server, aus einem Cache oder einer lokalen Ressource empfangen hat. |
| [`responseEnd`](/de/docs/Web/API/PerformanceTiming/responseEnd) | Wenn der Browser das letzte Byte der Antwort empfangen hat oder wenn die Verbindung geschlossen wird, falls dies zuerst geschah, vom Server, dem Cache oder einer lokalen Ressource. |
| [`domLoading`](/de/docs/Web/API/PerformanceTiming/domLoading) |
Wenn der Parser seine Arbeit begonnen hat, also wenn sein
[`Document.readyState`](/de/docs/Web/API/Document/readyState) zu
'loading' wechselt und das entsprechende
[`readystatechange`](/de/docs/Web/API/Document/readystatechange_event)
Ereignis ausgelöst wird.
|
| [`unloadEventStart`](/de/docs/Web/API/PerformanceTiming/unloadEventStart) |
Wenn das [`unload`](/de/docs/Web/API/Window/unload_event)
Ereignis ausgelöst wurde, das die Zeit angibt, zu der das vorherige
Dokument im Fenster mit dem Entladen begonnen hat. Wenn es kein
vorheriges Dokument gibt oder wenn das vorherige Dokument oder einer
der benötigten Weiterleitungen nicht vom selben Ursprung stammt, wird
der Wert 0 zurückgegeben.
|
| [`unloadEventEnd`](/de/docs/Web/API/PerformanceTiming/unloadEventEnd) |
Wenn der
unload
Ereignishandler abgeschlossen ist. Wenn es kein vorheriges Dokument
gibt oder wenn das vorherige Dokument oder eine der benötigten
Weiterleitungen nicht vom selben Ursprung stammt, wird der Wert
0 zurückgegeben.
|
| [`domInteractive`](/de/docs/Web/API/PerformanceTiming/domInteractive) |
Wenn der Parser seine Arbeit am Hauptdokument beendet hat, also wenn
sein
Document.readyState
zu 'interactive' wechselt und das entsprechende
readystatechange
Ereignis ausgelöst wird.
|
| [`domContentLoadedEventStart`](/de/docs/Web/API/PerformanceTiming/domContentLoadedEventStart) |
Unmittelbar bevor der Parser das
DOMContentLoaded
Ereignis gesendet hat, das heißt direkt nachdem alle Skripte, die
direkt nach dem Parsen ausgeführt werden müssen, ausgeführt wurden.
|
| [`domContentLoadedEventEnd`](/de/docs/Web/API/PerformanceTiming/domContentLoadedEventEnd) | Unmittelbar nachdem alle Skripte, die so schnell wie möglich in beliebiger Reihenfolge ausgeführt werden müssen, ausgeführt wurden. |
| [`domComplete`](/de/docs/Web/API/PerformanceTiming/domComplete) |
Wenn der Parser seine Arbeit am Hauptdokument beendet hat, also wenn
sein
Document.readyState
zu 'complete' wechselt und das entsprechende
readystatechange
Ereignis ausgelöst wird.
|
| [`loadEventStart`](/de/docs/Web/API/PerformanceTiming/loadEventStart) |
Wenn das
load
Ereignis für das aktuelle Dokument gesendet wurde. Wenn dieses Ereignis
noch nicht gesendet wurde, wird 0 zurückgegeben.
|
| [`loadEventEnd`](/de/docs/Web/API/PerformanceTiming/loadEventEnd) |
Wenn der
load
Ereignishandler beendet ist, das heißt, wenn das Ladeereignis
abgeschlossen ist. Wenn dieses Ereignis noch nicht gesendet oder
abgeschlossen ist, wird 0 zurückgegeben.
|
Berechnung von Zeiten
Wir können diese Werte verwenden, um spezifische, interessante Zeiten zu messen:
const dns = time.domainLookupEnd - time.domainLookupStart;
const tcp = time.connectEnd - time.connectStart;
const tls = time.requestStart - time.secureConnectionStart;
Time to First Byte
Time to First Byte ist die Zeit zwischen navigationStart (Beginn der Navigation) und responseStart (wenn das erste Byte der Antwortdaten empfangen wird), verfügbar in der performanceTiming API:
const ttfb = time.responseStart - time.navigationStart;
Seitenladezeit
Seitenladezeit ist die Zeit zwischen navigationStart und dem Beginn des Ladevorgangs des aktuellen Dokuments. Diese sind nur in der performanceTiming API verfügbar.
let pageloadTime = time.loadEventStart - time.navigationStart;
DNS-Abfragezeit
Die DNS-Abfragezeit ist die Zeit zwischen domainLookupStart und domainLookupEnd. Diese sind in beiden, der performanceTiming und der performanceNavigationTiming APIs, verfügbar.
const dns = time.domainLookupEnd - time.domainLookupStart;
TCP
Die Zeit, die für das TCP Handshake benötigt wird, ist die Zeit zwischen Verbindungsbeginn und Verbindungsende:
const tcp = time.connectEnd - time.connectStart;
TLS-Verhandlung
secureConnectionStart wird undefined, wenn nicht verfügbar, 0, wenn HTTPS nicht verwendet wird, oder ein Zeitstempel, wenn verfügbar und verwendet. Mit anderen Worten, wenn eine sichere Verbindung verwendet wurde, ist secureConnectionStart truthy, und die Zeit zwischen secureConnectionStart und requestStart wird größer als 0 sein.
const tls = time.requestStart - time.secureConnectionStart;
Performance Entry API
Die oben genannten allgemeinen Performance-Timings sind veraltet, aber vollständig unterstützt. Wir haben jetzt die Performance Entry API, die das Markieren und Messen von Zeiten entlang des Navigations- und Ressourcenladeprozesses ermöglicht. Sie können auch Markierungen erstellen:
performance.getEntriesByType("navigation").forEach((navigation) => {
console.dir(navigation);
});
performance.getEntriesByType("resource").forEach((resource) => {
console.dir(resource);
});
performance.getEntriesByType("mark").forEach((mark) => {
console.dir(mark);
});
performance.getEntriesByType("measure").forEach((measure) => {
console.dir(measure);
});
performance.getEntriesByType("paint").forEach((paint) => {
console.dir(paint);
});
performance.getEntriesByType("frame").forEach((frame) => {
console.dir(frame);
});
In unterstützenden Browsern können Sie performance.getEntriesByType('paint') verwenden, um das Maß für first-paint und first-contentful-paint abzufragen. Wir verwenden performance.getEntriesByType('navigation') und performance.getEntriesByType('resource'), um die Navigations- und Ressourcen-Zeiten abzufragen.
Navigation Timing
Wenn ein Nutzer eine Website oder Anwendung anfordert, durchläuft der Nutzeragent eine Reihe von Schritten, darunter eine DNS-Abfrage, TCP-Handshakes und TLS-Verhandlung, bevor der Nutzeragent die eigentliche Anfrage stellt und die Server die angeforderten Assets zurücksenden. Der Browser parst dann die empfangenen Inhalte, baut den DOM, CSSOM, Zugänglichkeit und Render-Bäume auf und rendert schließlich die Seite. Sobald der Nutzeragent das Parsen des Dokuments beendet hat, setzt der Nutzeragent die Dokumentbereitschaft auf interaktiv. Wenn es verzögerte Skripte gibt, die geparst werden müssen, wird er es tun, dann das DOMContentLoaded auslösen, danach wird die Bereitschaft auf vollständig gesetzt. Das Dokument kann nun nachgelagerte Aufgaben bearbeiten, nach denen das Dokument als vollständig geladen markiert wird.
const navigationTimings = performance.getEntriesByType("navigation");
Das performance.getEntriesByType('navigation') gibt ein Array von PerformanceEntry Objekten für den navigation type zurück.

Vieles kann aus diesen Timings gewonnen werden. Im obigen Bild sehen wir über die name Eigenschaft, dass die Datei, die gemessen wird, dieses Dokument ist. Für die weitere Erklärung verwenden wir die folgende Variable:
const timing = performance.getEntriesByType("navigation")[0];
Protokoll
Wir können das verwendete Protokoll durch Abfrage überprüfen:
const protocol = timing.nextHopProtocol;
Es gibt das Netzwerkprotokoll zurück, das verwendet wurde, um die Ressource abzurufen: in diesem Fall h2 für http/2.
Komprimierung
Um die Einsparungsprozentsätze bei der Komprimierung zu erhalten, teilen wir die transferSize durch die decodedBodySize und subtrahieren das von 100%. Wir sehen eine Einsparung von über 74%.
const compressionSavings = 1 - timing.transferSize / timing.decodedBodySize;
Wir hätten
const compressionSavings = 1 - timing.encodedBodySize / timing.decodedBodySize;
verwenden können, aber die Verwendung von transferSize schließt die Overhead-Bytes ein.
Zum Vergleich können wir auf den Netzwerk-Tab schauen und sehen, dass wir 22,04 KB für eine unkomprimierte Dateigröße von 87,24 KB transferiert haben.

Wenn wir die Mathematik mit diesen Zahlen durchführen, erhalten wir dasselbe Ergebnis: 1 - (22,04 / 87,24) = 0,747. Die Navigationstiming ermöglicht es uns, programmgesteuert Transfergrößen und Bandbreiteneinsparungen zu überprüfen.
Beachten Sie, dass dies die Größe für dieses einzelne Dokument allein ist: für diese Ressource allein, nicht für alle Ressourcen zusammen. Die Dauer, Ladeereignisse und DOM-bezogene Timings beziehen sich jedoch auf die gesamte Navigation, nicht auf dieses einzelne Asset. Client-seitige Webanwendungen können schneller erscheinen als diese mit Transfergrößen unter 10000 und dekodierten Körpergrößen unter 30000, aber das bedeutet nicht, dass JavaScript, CSS oder Medien-Assets keinen Ballast hinzufügen. Das Überprüfen von Kompressionsverhältnissen ist wichtig, aber stellen Sie sicher, dass Sie auch die Dauer und die Zeit zwischen dem Ende des DOMContentLoaded-Events und dem vollständigen DOM überprüfen, da das Ausführen von JavaScript im Hauptthread über lange Zeiträume zu einer nicht antwortenden Benutzeroberfläche führen kann.
Anfragetime
Die API liefert nicht jede Messung, die Sie möglicherweise wünschen. Zum Beispiel, wie lange hat die Anfrage gedauert? Wir können die Messungen, die wir haben, verwenden, um unsere Antwort zu bekommen.
Um die Antwortzeit zu messen, ziehen Sie die Startzeit der Anforderung von der Startzeit der Antwort ab. Der Anfragebeginn ist der Moment unmittelbar bevor der Nutzeragent die Ressource vom Server, den relevanten Anwendungs-Caches oder den lokalen Ressourcen anfordert. Die Antwortbeginn ist die Zeit unmittelbar nachdem der HTTP-Parser des Nutzeragenten das erste Byte der Antwort von den relevanten Anwendungs-Caches, den lokalen Ressourcen oder dem Server erhält, was geschieht, nachdem die Anfrage empfangen und verarbeitet wurde.
const request = timing.responseStart - timing.requestStart;
Ladeereignisdauer
Indem Sie den Zeitstempel von unmittelbar bevor das Ladeereignis des aktuellen Dokuments ausgelöst wird von der Zeit subtrahieren, zu der das Ladeereignis des aktuellen Dokuments abgeschlossen ist, können Sie die Dauer des Ladeereignisses messen.
const load = timing.loadEventEnd - timing.loadEventStart;
DOMContentLoaded-Ereignis
Die Dauer des DOMContentLoaded-Ereignisses wird gemessen, indem der Zeitwert unmittelbar bevor der Nutzeragent das DOMContentLoaded-Ereignis auslöst von dem Zeitwert unmittelbar nach Abschluss des Ereignisses subtrahiert wird. Dieses Ereignis auf 50 ms oder schneller zu halten, trägt dazu bei, eine ansprechende Benutzeroberfläche sicherzustellen.
const DOMContentLoaded =
timing.domContentLoadedEventEnd - timing.domContentLoadedEventStart;
Dauer
Wir erhalten die Dauer. Die Dauer ist der Unterschied zwischen den Eigenschaften PerformanceNavigationTiming.loadEventEnd und PerformanceEntry.startTime.
Die PerformanceNavigationTiming-Schnittstelle bietet zudem Informationen darüber, welche Navigationsart Sie messen, indem sie navigate, reload oder back_forward zurückgibt.
Ressourcen-Timing
Während das Navigations-Timing zur Messung der Leistung der Hauptseite dient, in der Regel die HTML-Datei, über die alle anderen Assets angefordert werden, misst das Ressourcen-Timing die Zeiten für einzelne Ressourcen, die vom Hauptdokument aufgerufenen Assets und alle Ressourcen, die diese Ressourcen anfordern. Viele der Messungen sind ähnlich: Es gibt eine DNS-Abfrage, ein TCP-Handshake und der Beginn der sicheren Verbindung wird einmal pro Domäne durchgeführt.

Das Hauptaugenmerk liegt auf den einzelnen Ressourcen.