Auswirkungen großer DOM-Größen auf die Interaktivität und mögliche Maßnahmen

Große DOM-Größen haben einen größeren Einfluss auf die Interaktivität, als Sie vielleicht denken. In diesem Leitfaden wird erläutert, warum das passiert und was Sie tun können.

Wenn Sie eine Webseite erstellen, hat diese immer ein Document Object Model (DOM). Das DOM stellt die Struktur des HTML-Codes Ihrer Seite dar und ermöglicht JavaScript und CSS den Zugriff auf die Struktur und den Inhalt einer Seite.

Das Problem ist jedoch, dass die Größe des DOM die Fähigkeit eines Browsers beeinträchtigt, eine Seite schnell und effizient zu rendern. Je größer das DOM ist, desto aufwendiger ist es, die Seite zu rendern und das Rendering später im Seitenlebenszyklus zu aktualisieren.

Das kann auf Seiten mit sehr großen DOMs problematisch sein, wenn Interaktionen, die das DOM ändern oder aktualisieren, aufwendige Layoutarbeiten auslösen, die sich auf die Reaktionsfähigkeit der Seite auswirken. Aufwendige Layoutarbeiten können sich auf den INP-Wert (Interaction to Next Paint) einer Seite auswirken. Wenn eine Seite schnell auf Nutzerinteraktionen reagieren soll, ist es wichtig, dass die DOM-Größen nur so groß wie nötig sind.

Wann ist das DOM einer Seite zu groß?

Laut Lighthouse ist die DOM-Größe einer Seite zu groß, wenn sie 1.400 Knoten überschreitet. Lighthouse gibt Warnungen aus, wenn das DOM einer Seite mehr als 800 Knoten umfasst. Beispiel:

<ul>
  <li>List item one.</li>
  <li>List item two.</li>
  <li>List item three.</li>
</ul>

Im obigen Code gibt es vier DOM-Elemente: das <ul>-Element und seine drei untergeordneten <li>-Elemente. Ihre Webseite wird mit ziemlicher Sicherheit viel mehr Knoten haben. Daher ist es wichtig zu wissen, was Sie tun können, um die DOM-Größe im Blick zu behalten. Außerdem sollten Sie andere Strategien zur Optimierung der Rendering-Arbeit kennen, wenn Sie den DOM einer Seite so klein wie möglich gehalten haben.

Wie wirken sich große DOMs auf die Seitenleistung aus?

Große DOMs beeinträchtigen die Seitenleistung auf verschiedene Weise:

  1. Beim ersten Rendern der Seite. Wenn CSS auf eine Seite angewendet wird, wird eine Struktur ähnlich dem DOM erstellt, die als CSS Object Model (CSSOM) bezeichnet wird. Je spezifischer die CSS-Selektoren sind, desto komplexer wird das CSSOM. Außerdem wird mehr Zeit benötigt, um die erforderlichen Layout-, Stil-, Compositing- und Rendering-Vorgänge auszuführen, die zum Darstellen der Webseite auf dem Bildschirm erforderlich sind. Dieser zusätzliche Aufwand erhöht die Interaktionslatenz für Interaktionen, die früh während des Seitenaufbaus erfolgen.
  2. Wenn durch Interaktionen das DOM geändert wird, entweder durch Einfügen oder Löschen von Elementen oder durch Ändern von DOM-Inhalten und ‑Stilen, kann die Arbeit, die zum Rendern dieser Aktualisierung erforderlich ist, zu sehr aufwendigen Layout-, Stil-, Compositing- und Rendering-Vorgängen führen. Wie beim ersten Rendern der Seite kann eine Erhöhung der CSS-Selektorspezifität den Renderingaufwand erhöhen, wenn HTML-Elemente als Ergebnis einer Interaktion in das DOM eingefügt werden.
  3. Wenn JavaScript das DOM abfragt, werden Verweise auf DOM-Elemente im Arbeitsspeicher gespeichert. Wenn Sie beispielsweise document.querySelectorAll aufrufen, um alle <div>-Elemente auf einer Seite auszuwählen, können die Speicherkosten erheblich sein, wenn das Ergebnis eine große Anzahl von DOM-Elementen zurückgibt.
Ein Screenshot einer Long Task, die durch übermäßige Rendering-Arbeit im Leistungsbereich der Chrome-Entwicklertools verursacht wird. Der Callstack der langen Aufgabe zeigt, dass viel Zeit für die Neuberechnung von Seitenstilen sowie für das Vorrendern aufgewendet wurde.
Eine lange Aufgabe, wie sie im Leistungsprofiler in den Chrome-Entwicklertools dargestellt wird. Die lange Aufgabe wird durch das Einfügen von DOM-Elementen in ein großes DOM über JavaScript verursacht.

All diese Faktoren können sich auf die Interaktivität auswirken, aber der zweite Punkt in der Liste oben ist besonders wichtig. Wenn eine Interaktion zu einer Änderung am DOM führt, kann dies eine Menge Arbeit auslösen, die zu einem schlechten INP auf einer Seite beitragen kann.

Wie messe ich die DOM-Größe?

Es gibt verschiedene Möglichkeiten, die DOM-Größe zu messen. Bei der ersten Methode wird Lighthouse verwendet. Wenn Sie einen Audit ausführen, werden Statistiken zum DOM der aktuellen Seite im Audit „Übermäßige DOM-Größe vermeiden“ unter der Überschrift „Diagnose“ angezeigt. In diesem Abschnitt sehen Sie die Gesamtzahl der DOM-Elemente, das DOM-Element mit den meisten untergeordneten Elementen sowie das tiefste DOM-Element.

Eine einfachere Methode ist die Verwendung der JavaScript-Konsole in den Entwicklertools eines beliebigen gängigen Browsers. Um die Gesamtzahl der HTML-Elemente im DOM zu ermitteln, können Sie den folgenden Code in der Konsole verwenden, nachdem die Seite geladen wurde:

document.querySelectorAll('*').length;

Wenn Sie die Aktualisierung der DOM-Größe in Echtzeit sehen möchten, können Sie auch das Tool zur Leistungsüberwachung verwenden. Mit diesem Tool können Sie Layout- und Stilvorgänge (und andere Leistungsaspekte) mit der aktuellen DOM-Größe in Beziehung setzen.

Ein Screenshot des Leistungsmonitors in den Chrome-Entwicklertools. Auf der linken Seite sehen Sie verschiedene Aspekte der Seitenleistung, die während der gesamten Lebensdauer der Seite kontinuierlich überwacht werden können. Auf dem Screenshot werden die Anzahl der DOM-Knoten, die Layouts pro Sekunde und die Stil-Neuberechnungen pro Abschnitt aktiv überwacht.
Der Leistungsmonitor in den Chrome-Entwicklertools. In dieser Ansicht wird die aktuelle Anzahl der DOM-Knoten der Seite zusammen mit den Layoutvorgängen und Stil-Neuberechnungen pro Sekunde dargestellt.

Wenn die Größe des DOM sich dem Warnschwellenwert für die DOM-Größe von Lighthouse nähert oder ihn überschreitet, müssen Sie herausfinden, wie Sie die DOM-Größe reduzieren können, um die Reaktionsfähigkeit Ihrer Seite auf Nutzerinteraktionen zu verbessern und den INP Ihrer Website zu optimieren.

Wie kann ich die Anzahl der DOM-Elemente messen, die von einer Interaktion betroffen sind?

Wenn Sie eine langsame Interaktion im Labor analysieren, die Ihrer Meinung nach mit der Größe des DOM der Seite zusammenhängen könnte, können Sie herausfinden, wie viele DOM-Elemente betroffen waren. Wählen Sie dazu im Profiler eine beliebige Aktivität mit der Bezeichnung „Recalculate Style“ (Stil neu berechnen) aus und sehen Sie sich die Kontextdaten im unteren Bereich an.

Screenshot einer ausgewählten Aktivität zur Neuberechnung des Stils im Leistungsbereich der Chrome-Entwicklertools. Oben sehen Sie im Interaktions-Track eine Klickinteraktion. Der Großteil der Arbeit wird für die Neuberechnung von Formatierungen und Vorbereitungen für das Rendern aufgewendet. Unten wird ein Bereich mit weiteren Details zur ausgewählten Aktivität angezeigt. Dort ist zu sehen, dass 2.547 DOM-Elemente betroffen waren.
Anzahl der betroffenen Elemente im DOM beobachten, die durch die Neuberechnung von Stilen entstehen. Der schattierte Bereich der Interaktion im Interaktions-Track stellt den Teil der Interaktionsdauer dar, der über 200 Millisekunden lag. Das ist der festgelegte „gute“ Grenzwert für INP.

Im Screenshot oben sehen Sie, dass bei der Neuberechnung des Stils des Projekts (wenn ausgewählt) die Anzahl der betroffenen Elemente angezeigt wird. Der Screenshot oben zeigt einen Extremfall der Auswirkungen der DOM-Größe auf die Rendering-Arbeit auf einer Seite mit vielen DOM-Elementen. Diese Diagnoseinformationen sind jedoch in jedem Fall nützlich, um festzustellen, ob die Größe des DOM ein begrenzender Faktor dafür ist, wie lange es dauert, bis der nächste Frame als Reaktion auf eine Interaktion gerendert wird.

Wie kann ich die DOM-Größe reduzieren?

Neben der Überprüfung des HTML-Codes Ihrer Website auf unnötiges Markup besteht die wichtigste Möglichkeit, die DOM-Größe zu reduzieren, darin, die DOM-Tiefe zu verringern. Ein Hinweis darauf, dass Ihr DOM unnötig tief ist, ist, wenn Sie in den Entwicklertools Ihres Browsers auf dem Tab Elemente Markup sehen, das so aussieht:

<div>
  <div>
    <div>
      <div>
        <!-- Contents -->
      </div>
    </div>
  </div>
</div>

Wenn Sie solche Muster sehen, können Sie sie wahrscheinlich vereinfachen, indem Sie die DOM-Struktur reduzieren. Dadurch wird die Anzahl der DOM-Elemente reduziert und Sie haben wahrscheinlich die Möglichkeit, Seitenstile zu vereinfachen.

Die DOM-Tiefe kann auch ein Symptom der verwendeten Frameworks sein. Insbesondere bei komponentenbasierten Frameworks, die auf JSX basieren, müssen Sie mehrere Komponenten in einem übergeordneten Container verschachteln.

Viele Frameworks bieten jedoch die Möglichkeit, das Verschachteln von Komponenten durch die Verwendung von sogenannten Fragmenten zu vermeiden. Zu den komponentenbasierten Frameworks, die Fragmente als Funktion anbieten, gehören unter anderem:

Wenn Sie in Ihrem bevorzugten Framework Fragmente verwenden, können Sie die DOM-Tiefe reduzieren. Wenn Sie Bedenken haben, dass sich die Vereinfachung der DOM-Struktur auf das Styling auswirkt, sollten Sie modernere (und schnellere) Layoutmodi wie Flexbox oder Grid verwenden.

Weitere Strategien

Auch wenn Sie sich bemühen, Ihren DOM-Baum zu vereinfachen und unnötige HTML-Elemente zu entfernen, um den DOM so klein wie möglich zu halten, kann er immer noch recht groß sein und viele Rendering-Vorgänge auslösen, wenn er sich als Reaktion auf Nutzerinteraktionen ändert. Wenn Sie sich in dieser Situation befinden, können Sie einige andere Strategien in Betracht ziehen, um den Rendering-Aufwand zu begrenzen.

Additiven Ansatz in Betracht ziehen

Es kann sein, dass große Teile Ihrer Seite beim ersten Rendern für den Nutzer nicht sichtbar sind. Das könnte eine Gelegenheit sein, HTML verzögert zu laden, indem Sie diese Teile des DOM beim Start weglassen und sie erst hinzufügen, wenn der Nutzer mit den Teilen der Seite interagiert, für die die anfangs ausgeblendeten Aspekte der Seite erforderlich sind.

Dieser Ansatz ist sowohl beim ersten Laden als auch danach nützlich. Beim ersten Seitenaufruf fällt weniger Rendering-Arbeit an, was bedeutet, dass die ursprüngliche HTML-Nutzlast geringer ist und schneller gerendert wird. So haben Interaktionen in diesem wichtigen Zeitraum mehr Möglichkeiten, mit weniger Konkurrenz um die Aufmerksamkeit des Haupt-Threads ausgeführt zu werden.

Wenn viele Teile der Seite beim Laden zunächst ausgeblendet sind, kann dies auch andere Interaktionen beschleunigen, die ein erneutes Rendern auslösen. Da jedoch durch andere Interaktionen mehr Elemente zum DOM hinzugefügt werden, nimmt die Rendering-Arbeit im Laufe des Seitenlebenszyklus zu.

Das Hinzufügen von Elementen zum DOM im Laufe der Zeit kann schwierig sein und hat seine eigenen Nachteile. Wenn Sie diesen Ansatz verfolgen, senden Sie wahrscheinlich Netzwerkanfragen, um Daten abzurufen, mit denen das HTML gefüllt wird, das Sie als Reaktion auf eine Nutzerinteraktion auf der Seite einfügen möchten. Laufende Netzwerkanfragen werden zwar nicht auf INP angerechnet, können aber die wahrgenommene Latenz erhöhen. Zeigen Sie nach Möglichkeit einen Lade-Spinner oder einen anderen Indikator dafür an, dass Daten abgerufen werden, damit Nutzer wissen, dass etwas passiert.

Komplexität von CSS-Selektoren begrenzen

Wenn der Browser Selektoren in Ihrem CSS parst, muss er den DOM-Baum durchlaufen, um zu verstehen, wie und ob diese Selektoren auf das aktuelle Layout angewendet werden. Je komplexer diese Selektoren sind, desto mehr Arbeit muss der Browser leisten, um sowohl das anfängliche Rendern der Seite als auch die erhöhten Stilneuberechnungen und Layoutarbeiten durchzuführen, wenn sich die Seite aufgrund einer Interaktion ändert.

content-visibility-Property verwenden

CSS bietet die Eigenschaft content-visibility, mit der sich DOM-Elemente, die nicht auf dem Bildschirm zu sehen sind, verzögert rendern lassen. Wenn sich die Elemente dem Viewport nähern, werden sie bei Bedarf gerendert. Die Vorteile von content-visibility bestehen nicht nur darin, dass beim ersten Rendern der Seite ein erheblicher Teil der Rendering-Arbeit entfällt, sondern auch, dass das Rendern von Elementen, die sich nicht auf dem Bildschirm befinden, übersprungen wird, wenn das Seiten-DOM aufgrund einer Nutzerinteraktion geändert wird.

Fazit

Wenn Sie die DOM-Größe auf das unbedingt Notwendige beschränken, können Sie den INP-Wert Ihrer Website optimieren. So können Sie die Zeit verkürzen, die der Browser für Layout- und Rendering-Vorgänge benötigt, wenn das DOM aktualisiert wird. Auch wenn Sie die DOM-Größe nicht sinnvoll reduzieren können, gibt es einige Techniken, mit denen Sie die Rendering-Arbeit auf einen DOM-Teilbaum beschränken können, z. B. CSS-Containment und die CSS-Eigenschaft content-visibility.

Unabhängig davon, wie Sie vorgehen, wird Ihre Website für Nutzer reaktionsschneller, wenn Sie die Rendering-Arbeit minimieren und die Menge an Rendering-Arbeit reduzieren, die Ihre Seite als Reaktion auf Interaktionen ausführt. Das bedeutet, dass Sie einen niedrigeren INP für Ihre Website haben, was zu einer besseren Nutzererfahrung führt.