Anfänglichen Sichtbarkeitsstatus erkennen

Für ein genaues Leistungsmonitoring ist es wichtig, festzustellen, ob eine Seite ursprünglich im Hintergrund geladen wurde (z.B. in einem neuen Tab im Hintergrund geöffnet). Bei im Hintergrund geladenen Seiten kommt es häufig zu verzögertem Rendering und längeren Messwertzeiten (z. B. First Contentful Paint). Wenn Sie diese Seiten identifizieren, können Sie sie aus den Leistungsanalysen herausfiltern, um verzerrte Daten zu vermeiden.

Am genauesten lässt sich das mit der VisibilityStateEntry API messen. Sie zeichnet Änderungen der Sichtbarkeit auf der Leistungszeitachse des Browsers zuverlässig auf, unabhängig davon, wann Ihr Script tatsächlich ausgeführt wird.

Erkennung der anfänglichen Sichtbarkeit und der Hintergrundzeit

OBLIGATORISCH: Verwende performance.getEntriesByType('visibility-state'), um auf den genauen Sichtbarkeitsverlauf zuzugreifen. Verlassen Sie sich nicht ausschließlich auf die Prüfung von document.visibilityState zur Ausführungszeit, da dies anfällig für Race-Bedingungen ist.

/**
 * Accurately determines visibility state history using the Performance API.
 */
function getVisibilityInfo() {
  // Retrieve VisibilityStateEntry members:
  const entries = performance.getEntriesByType('visibility-state');
  
  if (entries.length > 0) {
    const firstEntry = entries[0];
    
    // If the first performance entry for visibility is 'hidden',
    // the page was loaded in the background.
    const initiallyBackgrounded = firstEntry.name === 'hidden';
    
    // Find the precise, high-resolution timestamp of when the page 
    // was first backgrounded.
    let timeBackgrounded = null;
    for (const entry of entries) {
      if (entry.name === 'hidden') {
        // entry.startTime is used because it provides the exact browser 
        // timestamp of the visibility change, which is required for precision
        timeBackgrounded = entry.startTime;
        break;
      }
    }

    return {
      initiallyBackgrounded,
      timeBackgrounded
    };
  }
}

Fallback-Strategien

In nicht unterstützten Umgebungen können Sie auf die Property document.visibilityState zurückgreifen oder auf das Ereignis visibilitychange warten.

OBLIGATORISCH: Sie müssen sich darüber im Klaren sein, dass dieser Fallback-Ansatz oft sehr ungenau ist, um den ursprünglichen Hintergrundstatus zu bestimmen. Da Scripts asynchron geladen und ausgeführt werden können, kann eine Seite in einem Hintergrund-Tab geöffnet und dann vom Nutzer in den Vordergrund gebracht werden, bevor das Script vollständig heruntergeladen und ausgeführt wurde. Wenn das Script schließlich ausgeführt wird, wird document.visibilityState synchron als 'visible' gelesen und Sie gehen fälschlicherweise davon aus, dass die Seite im Vordergrund geladen wurde. Der ursprüngliche ausgeblendete Status wird dabei vollständig ignoriert. Außerdem fehlt dem Fallback-Zeitstempel die interne Genauigkeit der Performance API. Wenn Präzision eine hohe Priorität hat, verwenden Sie den Fallback nicht.

/**
 * Fallback implementation using document.visibilityState.
 * This approach is prone to race conditions if the script loads asynchronously.
 */
function getFallbackVisibilityInfo() {
  // Check the state exactly when this script executes.
  // This will fail to detect an initial background state if the user 
  // foregrounded the page before this script executed.
  let initiallyBackgrounded = document.visibilityState === 'hidden';
  
  // If it's hidden now, we approximate that it was hidden from load (time 0).
  let timeBackgrounded = initiallyBackgrounded ? 0 : null;

  // Listen for future visibility changes to capture if it is backgrounded later.
  document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'hidden' && timeBackgrounded === null) {
      // performance.now() is used here as a fallback, but it only gives 
      // us the time the event listener fired, not the precise internal 
      // browser time the visibility actually changed.
      timeBackgrounded = performance.now();
    }
  });

  return {
    get initiallyBackgrounded() { return initiallyBackgrounded; },
    get timeBackgrounded() { return timeBackgrounded; }
  };
}

// Modern implementation using VisibilityStateEntry API.
function getVisibilityInfo() {
  // Code omitted here would be the same modern
  // implementation shown earlier in this guide
  // ...
}

// DO: Detect if the VisibilityStateEntry API is available
if ('VisibilityStateEntry' in window) {
  // DO: If VisibilityStateEntry is available, use it first:
  getVisibilityInfo();
} else {
  // DO: If VisibilityStateEntry is unavailable, fall back to `document.visibilityState`:
  getFallbackVisibilityInfo();
}