Große DOM-Größen wirken sich stärker auf die Interaktivität aus, als Sie vielleicht denken. In diesem Leitfaden wird erläutert, warum das so ist und was Sie tun können.
Es gibt keinen Weg daran vorbei: Wenn Sie eine Webseite erstellen, hat diese ein Document Object Model (DOM). Das DOM stellt die Struktur des HTML-Codes Ihrer Seite dar und gewährt JavaScript und CSS 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. Generell gilt: Je größer das DOM, desto teurer ist es, die Seite zuerst zu rendern und das Rendering später im Seitenlebenszyklus zu aktualisieren.
Das wird bei Seiten mit sehr großen DOMs problematisch, wenn Interaktionen, die das DOM ändern oder aktualisieren, aufwendige Layoutarbeiten auslösen, die sich auf die Reaktionszeit der Seite auswirken. Aufwendige Layoutarbeiten können sich auf die Zeitspanne zwischen Interaktion und nächster Neuzeichnung (Interaction to Next Paint, INP) einer Seite auswirken. Wenn eine Seite schnell auf Nutzerinteraktionen reagieren soll, müssen die DOM-Größen nur so groß sein, wie es erforderlich ist.
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 800 Knoten überschreitet. Hier ein Beispiel für HTML-Code:
<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 Sicherheit viel mehr Knoten haben. Daher ist es wichtig, zu wissen, was Sie tun können, um die DOM-Größe im Auge zu behalten. Außerdem sollten Sie andere Strategien kennen, um das Rendering zu optimieren, sobald Sie das DOM einer Seite so klein wie möglich gemacht haben.
Wie wirken sich große DOMs auf die Seitenleistung aus?
Große DOMs wirken sich auf unterschiedliche Weise auf die Seitenleistung aus:
- Während des ersten Renderns der Seite. Wenn CSS auf eine Seite angewendet wird, wird eine Struktur erstellt, die dem DOM ähnelt und als CSS Object Model (CSSOM) bezeichnet wird. Je spezifischer die CSS-Selektoren sind, desto komplexer wird das CSSOM und desto mehr Zeit ist erforderlich, um die erforderlichen Layout-, Stil-, Komposition- und Malarbeiten auszuführen, die erforderlich sind, um die Webseite auf dem Bildschirm zu zeichnen. Diese zusätzliche Arbeit erhöht die Interaktionslatenz für Interaktionen, die früh beim Laden der Seite erfolgen.
- Wenn Interaktionen das DOM ändern, entweder durch Einfügen oder Löschen von Elementen oder durch Ändern von DOM-Inhalten und ‑Styles, kann die für das Rendern dieser Aktualisierung erforderliche Arbeit sehr kostspielig sein. Wie beim ersten Rendern der Seite kann eine erhöhte Spezifität des CSS-Selektors die Renderarbeit erhöhen, wenn HTML-Elemente als Ergebnis einer Interaktion in das DOM eingefügt werden.
- 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.
All diese Faktoren können sich auf die Interaktivität auswirken, aber der zweite Punkt in der Liste oben ist von besonderer Bedeutung. Wenn eine Interaktion zu einer Änderung am DOM führt, kann das viel Arbeit verursachen, was zu einer schlechten INP auf einer Seite beitragen kann.
Wie messe ich die DOM-Größe?
Es gibt mehrere Möglichkeiten, die DOM-Größe zu messen. Bei der ersten Methode wird Lighthouse verwendet. Wenn Sie eine Analyse ausführen, finden Sie die Statistiken zum DOM der aktuellen Seite unter der Überschrift „Übermäßige DOM-Größe vermeiden“ in der Analyse. 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 abzurufen, können Sie nach dem Laden der Seite den folgenden Code in der Konsole verwenden:
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.
Wenn die Größe des DOM dem Warngrenzwert für die DOM-Größe von Lighthouse näherkommt oder diesen sogar überschreitet, müssen Sie die Größe des DOM reduzieren, damit Ihre Seite besser auf Nutzerinteraktionen reagieren kann und sich die INP Ihrer Website verbessern lässt.
Wie kann ich die Anzahl der DOM-Elemente messen, die von einer Interaktion betroffen sind?
Wenn Sie im Lab eine langsame Interaktion analysieren, die möglicherweise mit der Größe des DOM der Seite zusammenhängt, können Sie herausfinden, wie viele DOM-Elemente betroffen waren. Wählen Sie dazu im Profiler eine Aktivität mit der Bezeichnung „Stil neu berechnen“ aus und beobachten Sie die Kontextdaten im unteren Bereich.
Im obigen Screenshot sehen Sie, dass bei der Stilneuberechnung des Werks (wenn ausgewählt) die Anzahl der betroffenen Elemente angezeigt wird. Der obige Screenshot zeigt einen Extremfall der Auswirkungen der DOM-Größe auf das Rendern 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 Prüfung des HTML-Codes Ihrer Website auf unnötiges Markup besteht die Hauptmethode zur Verringerung der DOM-Größe darin, die DOM-Tiefe zu reduzieren. Ein Hinweis darauf, dass Ihr DOM möglicherweise unnötig tief ist, ist, wenn Sie in den Entwicklertools Ihres Browsers auf dem Tab Elemente Markup sehen, das in etwa 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 flach gestalten. Dadurch wird die Anzahl der DOM-Elemente reduziert und Sie haben wahrscheinlich die Möglichkeit, die Seitenstile zu vereinfachen.
Die DOM-Tiefe kann auch ein Symptom der von Ihnen verwendeten Frameworks sein. Insbesondere bei komponentenbasierten Frameworks wie solchen, die auf JSX basieren, müssen Sie mehrere Komponenten in einem übergeordneten Container verschachteln.
Mit vielen Frameworks können Sie jedoch das Verschachteln von Komponenten vermeiden, indem Sie sogenannte Fragmente verwenden. Zu den komponentenbasierten Frameworks, die Fragmente als Funktion anbieten, gehören unter anderem:
Wenn Sie Fragmente in Ihrem Framework verwenden, können Sie die DOM-Tiefe reduzieren. Wenn Sie Bedenken bezüglich der Auswirkungen der flachen DOM-Struktur auf das Styling haben, sollten Sie modernere (und schnellere) Layoutmodi wie Flexbox oder Grid verwenden.
Weitere Strategien
Selbst wenn Sie sich Mühe geben, den DOM-Baum zu flach zu halten und unnötige HTML-Elemente zu entfernen, um das DOM so klein wie möglich zu halten, kann es immer noch ziemlich groß sein und viel Rendering-Arbeit auslösen, da es sich als Reaktion auf Nutzerinteraktionen ändert. In diesem Fall gibt es einige andere Strategien, mit denen Sie die Renderarbeit einschränken können.
Einen additiven Ansatz in Betracht ziehen
Es kann sein, dass große Teile Ihrer Seite beim ersten Rendern für den Nutzer nicht sichtbar sind. Dies könnte eine Gelegenheit sein, HTML per Lazy Loading zu laden, indem diese Teile des DOM beim Start weggelassen, aber hinzugefügt werden, wenn der Nutzer mit den Teilen der Seite interagiert, für die die ursprünglich ausgeblendeten Aspekte der Seite erforderlich sind.
Dieser Ansatz ist sowohl beim ersten Laden als auch möglicherweise danach nützlich. Beim ersten Laden der Seite müssen Sie weniger Rendering-Arbeit im Voraus erledigen. Das bedeutet, dass die anfängliche HTML-Nutzlast geringer ist und schneller gerendert wird. So haben Interaktionen in dieser wichtigen Phase mehr Möglichkeiten, ausgeführt zu werden, da sie weniger um die Aufmerksamkeit des Hauptthreads konkurrieren müssen.
Wenn viele Teile der Seite beim Laden zunächst ausgeblendet sind, können auch andere Interaktionen beschleunigt werden, die ein erneutes Rendern auslösen. Da jedoch durch andere Interaktionen mehr zum DOM hinzugefügt wird, steigt die Rendering-Arbeit, wenn das DOM während des gesamten Seitenlebenszyklus wächst.
Das DOM im Laufe der Zeit zu erweitern, kann schwierig sein und hat seine eigenen Vor- und Nachteile. Wenn Sie diese Methode verwenden, senden Sie wahrscheinlich Netzwerkanfragen, um Daten für das HTML-Format zu erhalten, das Sie der Seite als Reaktion auf eine Nutzerinteraktion hinzufügen möchten. Laufende Netzwerkanfragen werden zwar nicht auf die INP angerechnet, können aber die wahrgenommene Latenz erhöhen. Zeigen Sie nach Möglichkeit einen Ladebalken oder eine andere Anzeige, dass Daten abgerufen werden, damit Nutzer wissen, dass etwas passiert.
Komplexität von CSS-Selektoren begrenzen
Wenn der Browser Selektoren in Ihrem CSS analysiert, muss er den DOM-Baum durchlaufen, um zu verstehen, wie und ob diese Selektoren auf das aktuelle Layout angewendet werden. Je komplexer diese Auswahlen sind, desto mehr Arbeit muss der Browser leisten, um sowohl das erste Rendern der Seite als auch die zusätzlichen Stilneuberechnungen und Layoutarbeiten auszuführen, wenn sich die Seite aufgrund einer Interaktion ändert.
Property content-visibility
verwenden
CSS bietet die Eigenschaft content-visibility
, mit der sich DOM-Elemente außerhalb des Bildschirms träge rendern lassen. Sobald sich die Elemente dem Viewport nähern, werden sie auf Anfrage gerendert. Die Vorteile von content-visibility
beschränken sich nicht nur auf eine erhebliche Reduzierung der Rendering-Arbeit beim ersten Seitenaufbau, sondern auch auf das Überspringen des Renderings für Elemente außerhalb des Bildschirms, wenn das DOM der Seite aufgrund einer Nutzerinteraktion geändert wird.
Fazit
Wenn Sie die DOM-Größe auf das Notwendige beschränken, können Sie die INP Ihrer Website optimieren. So lässt sich die Zeit verkürzen, die der Browser für das Layout und Rendering benötigt, wenn das DOM aktualisiert wird. Auch wenn Sie die DOM-Größe nicht wesentlich reduzieren können, gibt es einige Techniken, mit denen Sie die Rendering-Arbeit auf einen DOM-Unterbaum beschränken können, z. B. CSS-Begrenzung und das CSS-Attribut content-visibility
.
Unabhängig davon, wie Sie vorgehen, sollten Sie eine Umgebung schaffen, in der die Rendering-Arbeit minimiert wird. Außerdem sollten Sie die Menge der Rendering-Arbeit reduzieren, die Ihre Seite als Reaktion auf Interaktionen ausführt. Das Ergebnis ist, dass Ihre Website für Nutzer reaktionsschneller erscheint, wenn sie mit ihr interagieren. Das bedeutet, dass Sie einen niedrigeren INP für Ihre Website haben, was sich in einer besseren Nutzererfahrung niederschlägt.