Start · Sprachen · JavaScript · Referenz · PerformancePaintTiming.toJSON()

PerformancePaintTiming.toJSON()

Methode

Gibt ein einfaches Objekt mit den Eigenschaften eines <code>PerformancePaintTiming</code>-Eintrags zurück, z. B. für <code>JSON.stringify()</code> oder für die Übertragung an einen Server.

seit JavaScript Baseline: alle modernen Browser (Chrome 60+, Firef Kategorie: webapi

Signatur

PerformancePaintTiming.prototype.toJSON()

Beschreibung

toJSON() ist die Serialisierungsmethode von PerformancePaintTiming. Sie erzeugt ein einfaches JavaScript-Objekt, das die öffentlichen Eigenschaften des Paint-Eintrags enthält. Das sind vor allem name ("first-paint" oder "first-contentful-paint"), entryType (immer "paint"), startTime und duration (bei Paint-Einträgen immer 0).

Gebraucht wird die Methode vor allem beim Real User Monitoring (RUM): Paint-Zeitpunkte wie First Contentful Paint (FCP) werden im Browser erfasst und als JSON an einen Analyse-Endpunkt geschickt. JSON.stringify() ruft toJSON() automatisch auf. Ohne diese Methode würde ein Performance-Eintrag nur zu {} serialisiert, weil seine Eigenschaften als Getter auf dem Prototyp liegen und keine eigenen Eigenschaften der Instanz sind.

Das zurückgegebene Objekt ist eine Momentaufnahme. Es hat keine Verbindung mehr zum ursprünglichen Eintrag und kann beliebig verändert oder erweitert werden, z. B. um die URL oder den Gerätetyp.

Rückgabewert

Typ
Object
Beschreibung
Ein einfaches Objekt mit den Eigenschaften name, entryType, startTime und duration. In neueren Browsern kommen zusätzlich paintTime und presentationTime hinzu (aus dem PaintTimingMixin). Zurückgegeben wird ein Objekt, kein JSON-String.

Beispiele

Paint-Einträge per PerformanceObserver serialisieren

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // toJSON() liefert ein einfaches Objekt
    console.log(entry.toJSON());
  }
});

// buffered: true liefert auch Einträge, die schon vor dem Registrieren entstanden sind
observer.observe({ type: 'paint', buffered: true });
{ name: 'first-paint', entryType: 'paint', startTime: 412.3, duration: 0 } { name: 'first-contentful-paint', entryType: 'paint', startTime: 412.3, duration: 0 }

First Contentful Paint an einen Analyse-Server senden

const sendFcp = (entry) => {
  const payload = {
    ...entry.toJSON(),
    page: location.pathname,
    timestamp: Date.now(),
  };
  // sendBeacon funktioniert auch noch beim Verlassen der Seite
  navigator.sendBeacon('/analytics/paint', JSON.stringify(payload));
};

new PerformanceObserver((list, obs) => {
  const fcp = list.getEntriesByName('first-contentful-paint')[0];
  if (fcp) {
    sendFcp(fcp);
    obs.disconnect();
  }
}).observe({ type: 'paint', buffered: true });

Unterschied zwischen JSON.stringify mit und ohne toJSON

const [entry] = performance.getEntriesByType('paint');

if (entry) {
  // JSON.stringify ruft toJSON() automatisch auf
  console.log(JSON.stringify(entry));

  // Getter liegen auf dem Prototyp, deshalb gibt es keine eigenen Schlüssel
  console.log(Object.keys(entry));

  // Das toJSON()-Ergebnis hat echte eigene Eigenschaften
  console.log(Object.keys(entry.toJSON()));
}
{"name":"first-paint","entryType":"paint","startTime":412.3,"duration":0} [] ["name", "entryType", "startTime", "duration"]

// Wichtig · Fallstricke

  • Kein String: toJSON() gibt ein Objekt zurück. Einen JSON-String erhält man erst mit JSON.stringify(entry) oder JSON.stringify(entry.toJSON()).
  • Spread und Object.assign() funktionieren nicht direkt: { ...entry } ergibt ein leeres Objekt, weil die Eigenschaften Getter auf dem Prototyp sind. Deshalb immer { ...entry.toJSON() } verwenden.
  • Browser-Kompatibilität: Firefox und Safari melden nur first-contentful-paint, first-paint gibt es dort nicht. Die neueren Felder paintTime und presentationTime sind noch nicht überall vorhanden. Der Code sollte also nicht auf bestimmte Schlüssel angewiesen sein.
  • Hintergrund-Tabs: Wird eine Seite im Hintergrund geladen, entstehen unter Umständen gar keine Paint-Einträge. Dann wird toJSON() nie aufgerufen.
  • Zeitbasis: startTime ist relativ zu performance.timeOrigin und keine Unix-Zeit. Für absolute Zeitpunkte muss man performance.timeOrigin + startTime rechnen.