Start · Sprachen · JavaScript · Referenz · PerformanceLongAnimationFrameTiming.firstUIEventTimestamp

PerformanceLongAnimationFrameTiming.firstUIEventTimestamp

Eigenschaft

Liefert als <code>DOMHighResTimeStamp</code> den Zeitpunkt des ersten UI-Ereignisses (z. B. Maus- oder Tastaturereignis), das während des langen Animation-Frames in die Warteschlange kam.

seit JavaScript Chromium 123+ (Chrome, Edge, Opera); nicht in Fire Kategorie: webapi

Signatur

PerformanceLongAnimationFrameTiming.firstUIEventTimestamp

Beschreibung

Die schreibgeschützte Eigenschaft firstUIEventTimestamp gehört zur Long Animation Frames API (LoAF). Sie gibt den Zeitpunkt zurück, zu dem das erste UI-Ereignis – etwa ein click, keydown oder pointerdown – im laufenden Frame in die Warteschlange kam. Gemessen wird relativ zu performance.timeOrigin, also auf derselben Zeitachse wie startTime und performance.now().

Nützlich ist der Wert vor allem, um Eingabeverzögerungen zu untersuchen: Liegt firstUIEventTimestamp deutlich vor dem Zeitpunkt, an dem der Frame mit dem Rendern fertig war (startTime + duration), dann hat die Benutzereingabe lange warten müssen. So lassen sich schlechte Werte der Metrik Interaction to Next Paint (INP) einem bestimmten langen Frame und damit bestimmten Skripten (scripts) zuordnen.

Gab es in dem Frame kein UI-Ereignis, ist der Wert 0. Einträge erhältst du über einen PerformanceObserver mit dem Typ "long-animation-frame". Als lang gilt ein Frame, wenn er länger als 50 ms dauert.

Rückgabewert

Typ
DOMHighResTimeStamp (number)
Beschreibung
Zeitpunkt in Millisekunden (mit Nachkommastellen) relativ zu performance.timeOrigin, zu dem das erste UI-Ereignis im Frame in die Warteschlange kam. 0, wenn es in diesem Frame kein UI-Ereignis gab.

Beispiele

Lange Frames mit Benutzereingabe protokollieren

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Frames ohne UI-Ereignis überspringen
    if (entry.firstUIEventTimestamp === 0) continue;

    console.log(
      `Langer Frame: ${entry.duration.toFixed(1)} ms, ` +
      `erstes UI-Ereignis bei ${entry.firstUIEventTimestamp.toFixed(1)} ms`
    );
  }
});

observer.observe({ type: 'long-animation-frame', buffered: true });
Langer Frame: 142.3 ms, erstes UI-Ereignis bei 5321.7 ms

Wartezeit der Eingabe bis zum Rendern berechnen

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    const { firstUIEventTimestamp, startTime, duration } = entry;
    if (!firstUIEventTimestamp) continue;

    const frameEnde = startTime + duration;
    const wartezeit = frameEnde - firstUIEventTimestamp;

    if (wartezeit > 100) {
      console.warn(`Eingabe wartete ${Math.round(wartezeit)} ms auf das Rendern`);
      // Verursachende Skripte ausgeben
      for (const script of entry.scripts) {
        console.warn('  ->', script.sourceURL, Math.round(script.duration), 'ms');
      }
    }
  }
});

observer.observe({ type: 'long-animation-frame', buffered: true });
Eingabe wartete 187 ms auf das Rendern -> https://example.com/app.js 164 ms

Feature-Erkennung und Versand an ein Analyse-Backend

const unterstuetzt = PerformanceObserver.supportedEntryTypes?.includes('long-animation-frame');

if (unterstuetzt) {
  new PerformanceObserver((list) => {
    const daten = list.getEntries()
      .filter((e) => e.firstUIEventTimestamp > 0)
      .map((e) => ({
        start: Math.round(e.startTime),
        dauer: Math.round(e.duration),
        ersterUIEvent: Math.round(e.firstUIEventTimestamp),
        blockiert: Math.round(e.blockingDuration)
      }));

    if (daten.length) {
      navigator.sendBeacon('/api/loaf', JSON.stringify(daten));
    }
  }).observe({ type: 'long-animation-frame', buffered: true });
} else {
  console.log('Long Animation Frames API nicht verfügbar');
}
Long Animation Frames API nicht verfügbar // z. B. in Firefox/Safari

// Wichtig · Fallstricke

  • Browser-Unterstützung: Nur Chromium-Browser ab Version 123. Firefox und Safari unterstützen die API nicht. Prüfe vorher mit PerformanceObserver.supportedEntryTypes, ob sie verfügbar ist.
  • Der Wert 0 heißt kein UI-Ereignis und ist kein gültiger Zeitstempel. Filtere solche Einträge aus, bevor du rechnest.
  • Erfasst wird nur das erste UI-Ereignis im Frame. Weitere Eingaben im selben Frame tauchen nicht einzeln auf. Einzelne Interaktionen misst du genauer mit PerformanceEventTiming (Typ "event").
  • Der Zeitstempel zeigt, wann das Ereignis in die Warteschlange kam, nicht wann sein Handler lief.
  • Zeitstempel können aus Datenschutzgründen (Schutz vor Timing-Angriffen) gerundet sein.