Signatur
Beschreibung
Mit PerformanceServerTiming kann der Browser Messwerte auslesen, die der Server über den HTTP-Header Server-Timing mitschickt, zum Beispiel die Dauer von Datenbankabfragen, Cache-Treffer oder die Renderzeit einer Vorlage. So lassen sich Frontend- und Backend-Leistung in einer einzigen Real-User-Monitoring-Auswertung (RUM) zusammenführen.
Instanzen erzeugt man nicht selbst. Man erhält sie über die Eigenschaft serverTiming eines PerformanceResourceTiming-Eintrags oder eines PerformanceNavigationTiming-Eintrags. Jeder Eintrag im Header wird zu genau einem PerformanceServerTiming-Objekt.
Das Interface ist schreibgeschützt und hat folgende Eigenschaften:
name(string): Name der Metrik, z. B.dbduration(number): Dauer in Millisekunden aus dem Parameterdur, sonst0description(string): Beschreibung aus dem Parameterdesc, sonst ein leerer StringtoJSON(): gibt eine JSON-taugliche Darstellung des Objekts zurück
Ein Header wie Server-Timing: db;dur=53;desc="Datenbank", cache;desc="HIT", app;dur=47.2 ergibt drei Einträge.
Rückgabewert
PerformanceResourceTiming.serverTiming geliefert (Typ ReadonlyArray<PerformanceServerTiming>).Beispiele
Server-Timing der aktuellen Seite auslesen
// Server-Header: Server-Timing: db;dur=53;desc="Datenbank", app;dur=47.2
const [navigation] = performance.getEntriesByType('navigation');
for (const { name, duration, description } of navigation?.serverTiming ?? []) {
console.log(`${name}: ${duration} ms (${description || 'ohne Beschreibung'})`);
}
Metriken von fetch-Anfragen mit PerformanceObserver überwachen
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.serverTiming?.length) continue;
const metrics = entry.serverTiming.map((t) => t.toJSON());
console.log(new URL(entry.name).pathname, metrics);
}
});
observer.observe({ type: 'resource', buffered: true });
await fetch('/api/produkte');
Servermetriken an ein Monitoring-Backend senden
const sendServerTimings = () => {
const payload = performance
.getEntriesByType('resource')
.filter((e) => e.serverTiming.length > 0)
.map((e) => ({
url: e.name,
metriken: Object.fromEntries(
e.serverTiming.map((t) => [t.name, t.duration])
)
}));
if (payload.length) {
navigator.sendBeacon('/rum', JSON.stringify(payload));
}
};
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') sendServerTimings();
});
// Wichtig · Fallstricke
- Nur in sicheren Kontexten: Über HTTP ohne TLS bleibt
serverTimingein leeres Array (Safari hat das erst ab Version 16.4 unterstützt). - Cross-Origin: Bei Ressourcen von fremden Origins sind die Werte nur sichtbar, wenn der Server
Timing-Allow-Originsendet, z. B.Timing-Allow-Origin: https://example.com. Fehlt der Header, ist das Array leer. - Sicherheit: Die Werte sind für jedes Skript auf der Seite und in den DevTools sichtbar. Keine internen Details wie Hostnamen, SQL-Abfragen oder Benutzerdaten in
descsenden. Genaue Zeitangaben können außerdem Timing-Angriffe erleichtern, deshalb in der Produktion eher runden oder nur für eingeloggte Admins senden. durationist0, wenndurfehlt.0heißt also nicht unbedingt „keine Zeit gebraucht“.- Der Header kann auch als HTTP-Trailer gesendet werden, das unterstützen Browser bisher aber kaum.
- Auch in Web Workern verfügbar.