Signatur
Beschreibung
Über serverTiming kommen serverseitige Messwerte im Browser an. Der Server schickt dafür den HTTP-Antwort-Header Server-Timing mit, z. B. Server-Timing: db;dur=53;desc="Datenbank", cache;desc="HIT". Der Browser zerlegt diesen Header und stellt jeden Eintrag als PerformanceServerTiming-Objekt mit den Eigenschaften name, duration und description bereit.
Die Eigenschaft gibt es bei PerformanceResourceTiming-Einträgen (Bilder, Skripte, fetch-Aufrufe usw.) und bei PerformanceNavigationTiming, das von PerformanceResourceTiming erbt. Dort enthält sie die Metriken des HTML-Dokuments selbst. So lassen sich Backend-Zeiten wie Datenbankabfragen, Template-Rendering oder Cache-Treffer direkt im Real User Monitoring (RUM) zusammen mit den Frontend-Timings erfassen.
Hat die Antwort keinen Server-Timing-Header oder dürfen die Daten nicht offengelegt werden (siehe Hinweise zu CORS), ist das Array leer. Das Array ist ein unveränderlicher Schnappschuss. Wenn Sie es ändern, hat das keine Auswirkung auf den Performance-Eintrag.
Rückgabewert
PerformanceServerTiming-Objekten mit name (string), duration (number, Millisekunden, Standardwert 0) und description (string, Standardwert ""). Ohne Header oder bei gesperrtem Zugriff ist das Array leer.Beispiele
Server-Metriken der aktuellen Seite auslesen
// Antwort-Header des Servers:
// Server-Timing: db;dur=53.2;desc="Datenbank", render;dur=18, cache;desc="HIT"
const [navigation] = performance.getEntriesByType('navigation');
for (const { name, duration, description } of navigation.serverTiming) {
console.log(`${name}: ${duration} ms (${description})`);
}
Server-Timing aller fetch-Aufrufe laufend beobachten
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.initiatorType !== 'fetch') continue;
const metrics = Object.fromEntries(
entry.serverTiming.map((m) => [m.name, m.duration])
);
console.log(new URL(entry.name).pathname, metrics);
}
});
observer.observe({ type: 'resource', buffered: true });
await fetch('/api/produkte');
Metriken an einen RUM-Endpunkt senden
window.addEventListener('pagehide', () => {
const [nav] = performance.getEntriesByType('navigation');
const payload = {
url: location.pathname,
ttfb: nav.responseStart - nav.requestStart,
server: nav.serverTiming.map(({ name, duration, description }) => ({
name, duration, description
}))
};
navigator.sendBeacon('/rum', JSON.stringify(payload));
});
Server-Timing-Header in Node.js setzen
import http from 'node:http';
http.createServer(async (req, res) => {
const start = performance.now();
const daten = await new Promise((r) => setTimeout(() => r('[]'), 30)); // simulierte DB
const dbDauer = (performance.now() - start).toFixed(1);
res.setHeader('Server-Timing', `db;dur=${dbDauer};desc="Datenbank"`);
res.setHeader('Timing-Allow-Origin', 'https://www.example.com');
res.setHeader('Content-Type', 'application/json');
res.end(daten);
}).listen(3000);
// Wichtig · Fallstricke
- Cross-Origin: Bei Ressourcen von fremden Ursprüngen ist
serverTimingleer. Das ändert sich nur, wenn der Server den HeaderTiming-Allow-Originpassend setzt (z. B.Timing-Allow-Origin: *oder den konkreten Ursprung).Access-Control-Allow-Originreicht dafür nicht aus. - Nur sichere Kontexte: Die Daten stehen nur über HTTPS (bzw.
localhost) zur Verfügung. - Datenschutz und Sicherheit: Die Metriken kann jeder Seitenbesucher lesen. Schicken Sie keine internen Hostnamen, SQL-Abfragen, Versionsnummern oder Nutzerdaten im Header mit. Sehr genaue Zeitangaben können außerdem Timing-Angriffe erleichtern. Geben Sie den Header deshalb eher gerundet oder nur in bestimmten Umgebungen aus.
- Zwischengespeicherte Antworten: Kommt eine Ressource aus dem HTTP-Cache, enthält
serverTimingunter Umständen die alten Werte aus der gespeicherten Antwort. Diese Werte stammen nicht aus der aktuellen Anfrage. - Parsing: Fehlt
dur, istdurationgleich0. Ungültig formatierte Einträge werden stillschweigend übergangen. Metriken mit gleichem Namen bleiben alle erhalten. - Kompatibilität: Safari unterstützt die Eigenschaft erst ab Version 16.4. Prüfen Sie ältere Browser vorher mit
'serverTiming' in PerformanceResourceTiming.prototype. - Die Metriken erscheinen auch in den Browser-Entwicklertools (Netzwerk → Timing) und helfen so beim Debuggen.