First Input Delay optimieren

Schneller auf Interaktionen der Nutzer reagieren

Ich habe geklickt, aber nichts passiert! Warum kann ich nicht mit dieser Seite interagieren? 😢

First Contentful Paint (FCP) und Largest Contentful Paint (LCP) sind beides Messwerte, die die Zeit messen, die benötigt wird, um Inhalte auf einer Seite visuell zu rendern. Die Farbintensität ist zwar wichtig, erfasst aber nicht die Ladereaktion – also nicht, wie schnell eine Seite auf Nutzerinteraktionen reagiert.

First Input Delay (FID) ist ein Core Web Vitals-Messwert, der den ersten Eindruck eines Nutzers hinsichtlich der Interaktivität und Reaktionsfähigkeit einer Website erfasst. Sie misst die Zeit von der ersten Interaktion eines Nutzers mit einer Seite bis zu dem Zeitpunkt, zu dem der Browser tatsächlich auf diese Interaktion reagieren konnte. FID ist ein Feldmesswert und kann nicht in einer Laborumgebung simuliert werden. Zum Messen der Antwortverzögerung ist eine echte Nutzerinteraktion erforderlich.

Gute fid-Werte sind 2,5 Sekunden, schlechte Werte größer als 4,0 Sekunden.Alles dazwischen muss verbessert werden.

Zur Vorhersage von FID im Lab empfehlen wir die Total Blocking Time (TBT). Sie messen verschiedene Dinge, aber Verbesserungen bei TBT entsprechen in der Regel Verbesserungen von FID.

Die Hauptursache für eine schlechte FID ist eine intensive JavaScript-Ausführung. Wenn Sie optimieren, wie JavaScript auf Ihrer Webseite geparst, kompiliert und ausführt, wird die FID direkt reduziert.

Komplexe JavaScript-Ausführung

Der Browser kann nicht auf die meisten Nutzereingaben reagieren, während er JavaScript im Hauptthread ausführt. Mit anderen Worten: Der Browser kann nicht auf Nutzerinteraktionen reagieren, während der Hauptthread ausgelastet ist. So können Sie dies verbessern:

Lange Aufgaben aufteilen

Wenn Sie bereits versucht haben, die Menge an JavaScript, das auf einer einzelnen Seite geladen wird, zu reduzieren, kann es sinnvoll sein, lang andauernden Code in kleinere, asynchrone Aufgaben zu unterteilen.

Lange Aufgaben sind JavaScript-Ausführungszeiträume, in denen Nutzer möglicherweise feststellen, dass Ihre UI nicht reagiert. Jeder Code, der den Hauptthread für 50 ms oder länger blockiert, kann als lange Aufgabe charakterisiert werden. Lange Aufgaben sind ein Zeichen für JavaScript-Bloat, d. h. es können mehr geladen und ausgeführt werden, als der Nutzer aktuell benötigt. Wenn Sie lange Aufgaben aufteilen, kann dies die Eingabeverzögerung auf Ihrer Website reduzieren.

Lange Aufgaben in den Chrome-Entwicklertools
Die Chrome-Entwicklertools visualisieren lange Aufgaben im Bereich „Leistung“

FID sollte sich deutlich verbessern, wenn Sie Best Practices wie die Codeaufteilung und die Aufteilung langer Aufgaben anwenden. TBT ist zwar kein Feldmesswert, doch es ist nützlich, um den Fortschritt hin zur Verbesserung sowohl der Zeit bis zur Interaktivität (Time To Interactive, TTI) als auch von FID zu überprüfen.

Seite für Interaktionsmöglichkeiten optimieren

Es gibt eine Reihe häufiger Ursachen für schlechte FID- und TBT-Werte in Web-Apps, die stark auf JavaScript basieren:

Die Ausführung eines eigenen Skripts kann die Bereitschaft zur Interaktion verzögern

  • Überflüssige JavaScript-Größen, lange Ausführungszeiten und eine ineffiziente Aufteilung können dazu führen, dass eine Seite langsamer auf Nutzereingaben reagieren und sich auf FID, TBT und TTI auswirken kann. Das progressive Laden von Code und Funktionen kann dabei helfen, diese Arbeit zu verteilen und die Interaktionsbereitschaft zu verbessern.
  • Serverseitig gerenderte Apps sehen vielleicht so aus, als würden Pixel schnell auf dem Bildschirm dargestellt werden. Achten Sie aber darauf, dass Nutzerinteraktionen durch umfangreiche Skriptausführungen (z. B. Rehydration zur Verbindung von Event-Listenern) blockiert werden. Dies kann bei routenbasierter Codeaufteilung mehrere hundert Millisekunden, manchmal sogar Sekunden dauern. Ziehen Sie in Betracht, während der Build-Dauer mehr Logik auf die Serverseite zu verlagern oder mehr Inhalte statisch zu generieren.

Nachfolgend sind die TBT-Werte vor und nach der Optimierung des Ladens von eigenen Skripts für eine Anwendung aufgeführt. Indem das Laden und Ausführen von kostspieligen Skripts für eine nicht notwendige Komponente aus dem kritischen Pfad verschoben wurde, konnten Nutzer viel früher mit der Seite interagieren.

Verbesserungen des TBT-Scores in Lighthouse nach der Optimierung des eigenen Skripts.

Der Datenabruf kann sich auf viele Aspekte der Interaktionsbereitschaft auswirken

  • Das Warten auf einen Wasserfall aus kaskadierenden Abrufen (z.B. JavaScript und Datenabrufe für Komponenten) kann sich auf die Interaktionslatenz auswirken. Versuchen Sie, die Abhängigkeit von kaskadierenden Datenabrufen so gering wie möglich zu halten.
  • Große Inline-Datenspeicher können HTML-Parsing-Zeit übertragen und sich sowohl auf Paint- als auch auf Interaktionsmesswerte auswirken. Versuchen Sie, die Datenmenge auf der Clientseite zu minimieren.

Die Ausführung von Drittanbieter-Skripts kann die Interaktionslatenz verzögern

  • Viele Websites beinhalten Tags und Analysen von Drittanbietern, die das Netzwerk belasten und dazu führen können, dass der Hauptthread in regelmäßigen Abständen nicht mehr reagiert, was die Interaktionslatenz beeinträchtigt. Testen Sie das On-Demand-Laden von Drittanbietercode. Laden Sie z. B. Anzeigen, die „below the fold“ (mit Scrollen sichtbar) nicht geladen werden, erst, wenn sie näher an den Darstellungsbereich gescrollt werden.
  • In einigen Fällen können Drittanbieterskripts eigene Skripts in Bezug auf Priorität und Bandbreite im Hauptthread vorziehen, wodurch sich auch verzögert, bis eine Seite interaktionsbereit ist. Versuchen Sie, zuerst zu laden, was Ihrer Meinung nach den Nutzern den größten Nutzen bietet.

Web Worker verwenden

Ein blockierter Hauptthread ist eine der Hauptursachen für Eingabeverzögerungen. Mit Web-Workern kann JavaScript in einem Hintergrundthread ausgeführt werden. Das Verschieben von Nicht-UI-Vorgängen in einen separaten Worker-Thread kann die Blockierzeit für den Hauptthread reduzieren und somit FID verbessern.

Erwägen Sie die Verwendung der folgenden Bibliotheken, um die Verwendung von Web Workern auf Ihrer Website zu vereinfachen:

  • Comlink: Eine Hilfsbibliothek, die postMessage abstrahiert und leichter zu verwenden ist
  • Workway: Ein Allzweck-Web Worker-Exporter
  • Worker-Prozess: Verschieben Sie ein Modul in einen Web-Worker.

JavaScript-Ausführungszeit reduzieren

Wenn Sie die Menge an JavaScript auf Ihrer Seite begrenzen, benötigt der Browser weniger Zeit für die Ausführung von JavaScript-Code. Dadurch kann der Browser schneller auf Nutzerinteraktionen reagieren.

So reduzieren Sie die Menge an JavaScript, das auf Ihrer Seite ausgeführt wird:

  • Nicht verwendetes JavaScript aufschieben
  • Nicht verwendete Polyfills minimieren

Nicht verwendetes JavaScript aufschieben

JavaScript blockiert standardmäßig das Rendering. Wenn der Browser auf ein Skript-Tag stößt, das mit einer externen JavaScript-Datei verknüpft ist, muss die zugehörige Aktion angehalten werden. Der JavaScript-Code muss dann heruntergeladen, geparst, kompiliert und ausgeführt werden. Daher sollte nur der Code geladen werden, der für die Seite oder als Antwort auf Nutzereingabe erforderlich ist.

Auf dem Tab Abdeckung in den Chrome-Entwicklertools sehen Sie, wie viel JavaScript auf Ihrer Webseite nicht verwendet wird.

Tab „Abdeckung“

So reduzieren Sie nicht verwendetes JavaScript:

  • Teilen Sie Ihr Bundle mit Code in mehrere Blöcke auf
  • Alle unkritischen JavaScripts, einschließlich Drittanbieter-Skripts, mit async oder defer aufschieben

Bei der Codeaufteilung wird ein einzelnes großes JavaScript-Bundle in kleinere Blöcke unterteilt, die unter Bedingungen geladen werden können (auch als Lazy Loading bezeichnet). Die meisten neueren Browser unterstützen die dynamische Importsyntax, mit der Module bei Bedarf abgerufen werden können:

import('module.js').then((module) => {
  // Do something with the module.
});

Durch das dynamische Importieren von JavaScript bei bestimmten Nutzerinteraktionen (z. B. Ändern einer Route oder Aufrufen eines modalen Fensters) wird dafür gesorgt, dass Code, der nicht für den anfänglichen Seitenaufbau verwendet wird, nur abgerufen wird, wenn es erforderlich ist.

Neben der allgemeinen Browserunterstützung kann die dynamische Importsyntax in vielen verschiedenen Build-Systemen verwendet werden.

  • Wenn Sie Webpack, Rollup oder Parcel als Modul-Bundler verwenden, nutzen Sie die Vorteile der dynamischen Importunterstützung.
  • Clientseitige Frameworks wie React, Angular und Vue bieten Abstraktionen, mit denen Lazy Loading auf Komponentenebene vereinfacht wird.

Abgesehen von der Codeaufteilung sollten Sie immer async oder defer für Skripts verwenden, die für kritischen Pfad oder ohne Scrollen sichtbare Inhalte nicht erforderlich sind.

<script defer src="…"></script>
<script async src="…"></script>

Sofern es keinen bestimmten Grund dafür gibt, sollten alle Drittanbieterskripts standardmäßig mit defer oder async geladen werden.

Nicht verwendete Polyfills minimieren

Wenn Sie Ihren Code mit moderner JavaScript-Syntax erstellen und auf APIs für moderne Browser verweisen, müssen Sie ihn transpilieren und Polyfills einfügen, damit er in älteren Browsern funktioniert.

Eines der größten Leistungsbedenken bei der Einbindung von Polyfills und transpiliertem Code in deine Website besteht darin, dass neuere Browser ihn nicht herunterladen müssen, wenn sie ihn nicht benötigen. Um die JavaScript-Größe deiner App zu reduzieren, solltest du nicht verwendete Polyfills so weit wie möglich minimieren und ihre Nutzung auf Umgebungen beschränken, in denen sie benötigt werden.

So optimieren Sie die Polyfill-Nutzung auf Ihrer Website:

  • Wenn Sie Babel als Transpiler verwenden, verwenden Sie @babel/preset-env, um nur die Polyfills einzuschließen, die für die gewünschten Browser erforderlich sind. Aktivieren Sie für Babel 7.9 die Option bugfixes, um nicht benötigte Polyfills weiter zu reduzieren.
  • Verwenden Sie das Muster „module/nomodule“, um zwei separate Bundles bereitzustellen (@babel/preset-env unterstützt dies auch über target.esmodules).

    <script type="module" src="modern.js"></script>
    <script nomodule src="legacy.js" defer></script>
    

    Viele neuere mit Babel kompilierte ECMAScript-Funktionen werden bereits in Umgebungen unterstützt, die JavaScript-Module unterstützen. Dadurch wird sichergestellt, dass nur transpilierter Code für Browser verwendet wird, die ihn tatsächlich benötigen.

Entwicklertools

Zum Messen und Debuggen von FID stehen mehrere Tools zur Verfügung:

  • Lighthouse 6.0 bietet keine Unterstützung für FID, da es sich um einen Feldmesswert handelt. Die Total Blocking Time (TBT) kann jedoch als Proxy verwendet werden. Optimierungen zur Verbesserung der TBT sollten auch den FID-Wert verbessern.

    Lighthouse 6.0.

  • Der Bericht zur Nutzererfahrung in Chrome enthält reale FID-Werte, die auf Ursprungsebene aggregiert wurden.

Wir danken Philip Walton, Kayce Basques, Ilya Grigorik und Annie Sullivan für ihre Rezensionen.