Browser-Painting und Überlegungen zur Web-Performance

Avatar of Georgy Marchuk
Georgy Marchuk am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Der Prozess, bei dem ein Webbrowser HTML, CSS und JavaScript in eine fertige *visuelle* Darstellung umwandelt, ist ziemlich komplex und beinhaltet ein gutes Stück Magie. Hier sind eine vereinfachte Reihe von Schritten, die der Browser durchläuft

  1. Der Browser erstellt das DOM und das CSSOM.
  2. Der Browser erstellt den Render-Tree, bei dem das DOM und die Stile aus dem CSSOM berücksichtigt werden (display: none-Elemente werden vermieden).
  3. Der Browser berechnet die Geometrie des Layouts und seiner Elemente basierend auf dem Render-Tree.
  4. Der Browser malt Pixel für Pixel, um die visuelle Darstellung zu erstellen, die wir auf dem Bildschirm sehen.

In diesem Artikel möchte ich mich auf den letzten Teil konzentrieren: das Malen (Painting).

All diese Schritte zusammen sind für einen Browser eine Menge Arbeit beim Laden… und tatsächlich nicht nur beim Laden, sondern jedes Mal, wenn das DOM (oder CSSOM) geändert wird. Deshalb lösen viele Webentwickler dieses Problem teilweise, indem sie eine Art Frontend-Framework verwenden, wie z. B. React, das neben vielen anderen Vorteilen dazu beitragen kann, Änderungen im DOM stark zu optimieren, um unnötige Neuberechnungen oder Renderings zu vermeiden.

Sie haben vielleicht Begriffe wie State, Component Rendering oder Immutability gehört. All diese haben etwas mit der Optimierung von DOM-Änderungen zu tun, oder anders ausgedrückt, nur dann Änderungen am DOM vorzunehmen, wenn es notwendig ist.

Um ein Beispiel zu geben: Der Zustand einer Webanwendung kann sich ändern, was zu einer Änderung der Benutzeroberfläche führt. Bestimmte (oder viele) Komponenten sind jedoch von dieser Änderung nicht betroffen. React hilft dabei, das Schreiben in das DOM für Elemente zu begrenzen, die tatsächlich von einer Zustandsänderung betroffen sind, und letztendlich das Rendering auf den kleinstmöglichen Teil der Webanwendung zu beschränken.

DOM/CSSOM → render tree → layout → painting

Das Browser-Painting ist jedoch auf seine Weise besonders, da es auch ohne Änderungen am DOM und/oder CSSOM auftreten kann.

Beispiel für eine Zusammenfassung der Seitenleistung

Das obige Diagramm wurde mit dem Performance-Panel von Chrome in den DevTools erstellt (mehr dazu später) und zeigt, wie viel Zeit jeder Task im Browser während der aufgezeichneten Zeit (0-7,12 s) nach dem Neuladen einer Seite beansprucht hat. Wie Sie sehen können, nimmt das Painting einen erheblichen Teil ein, und das ist nicht automatisch schlecht. In diesem speziellen Beispiel wird das erhöhte Painting durch eine Kombination aus animierten GIFs auf der Seite und Canvas-Zeichnungen (bei 60 fps) verursacht, die beide keine Änderungen am DOM oder seinen Stilen verursachen, aber dennoch ein Painting auslösen.

Ein weiteres gutes Beispiel für eine Funktion, die Painting ohne äußere Einwirkung auslösen kann, ist die CSS animation-Eigenschaft, und im Vergleich zu animierten GIFs oder Canvas ist sie wahrscheinlich häufiger im Web anzutreffen. Eine Animation wird normalerweise durch Benutzereingaben ausgelöst, wie z. B. Hover, aber dank animation und @keyframes Regeln können wir auch recht komplexe Animationen erstellen, die ohne viel Aufwand ständig auf der Seite laufen, was ziemlich erstaunlich ist.

Was einige vielleicht nicht erkennen, ist, dass diese Animationen leicht außer Kontrolle geraten und ständig Painting auslösen können, was uns viel Rechenleistung kosten kann. Natürlich gibt es einige Regeln, die verwendet werden können, um Painting zu vermeiden. Am offensichtlichsten ist die Beschränkung der Manipulation von Elementen auf die CSS-Eigenschaften transform und opacity, die standardmäßig kein Painting auslösen, es sei denn, es liegen besondere Umstände vor, wie z. B. die Animation eines SVG-Pfades.

Paint Flashing

Sie wissen wahrscheinlich, dass Chrome DevTools hat. Was Sie vielleicht nicht wissen, ist eine kleine Tastenkombination (Shift+Cmd+P auf Mac oder Control+Shift+P auf PC), die Sie *innerhalb der DevTools* verwenden können, um eine kleine Suchleiste und ein Befehlsmenü aufzurufen.

Befehlsmenü

Ich habe angefangen, darin zu stöbern, und neben vielen anderen nützlichen und unglaublich interessanten Optionen fiel mir ein Render-Panel auf.

Render-Panel

Auf den ersten Blick sehen Sie einige interessante Optionen, die bei der Fehlersuche bei Animationen im Web sehr hilfreich sein können, wie z. B. ein FPS-Meter.

FPS-Meter

Layer-Borders und Paint Flashing sind ebenfalls interessante Tools. Layer-Borders werden verwendet, um die Grenzen von Layern anzuzeigen, wie sie vom Browser gerendert werden, sodass jede Transformation oder Größenänderung leicht erkennbar ist. Paint Flashing dient dazu, Bereiche der Webseite hervorzuheben, in denen der Browser zum Neuzeichnen gezwungen wird.

Paint Flashing

Nachdem ich Paint Flashing entdeckt hatte, habe ich es als Erstes auf einem meiner Projekte ausprobiert. An den meisten Stellen gab es keine Probleme. Zum Beispiel wurde jede durch Scrollen ausgelöste Bewegung auf der Website durch die CSS-Eigenschaft transform angetrieben, die, wie wir gesehen haben, kein Painting verursacht. Das Painting war dort vorhanden, wo man es erwarten würde, wie z. B. Änderungen der Textfarbe beim Hovern, aber das sollte aufgrund seiner Größe und des Vorhandenseins nur beim Hovern über das Element kein großes Problem darstellen. Zusammenfassend lässt sich sagen, dass man immer etwas verbessern kann, auch wenn man den Code gestern geschrieben hat...

Aber eine Sache war ein Schlag ins Gesicht.

Es spielt keine Rolle, wie erfahren oder vorsichtig Sie sind, Sie können – und werden höchstwahrscheinlich – einen Fehler machen. Wir sind nur Menschen, und einige würden argumentieren, dass die Behebung eigener Fehler den größten Teil der Arbeit in der Entwicklung ausmacht. Damit ein Fehler jedoch behoben werden kann, müssen wir uns seiner bewusst sein… und genau hier hilft das Render-Panel.

Fallstudie

Werfen wir einen genaueren Blick auf das eigentliche Problem. Das Design kam mit der Anforderung eines verrauschten Hintergrunds. Diese Art von Effekt, den alte Fernseher hatten, wenn kein Signal vorhanden war.

Es ist bekannt, dass GIFs viele Probleme haben, wobei Performance sicherlich eines davon ist, daher konnte ich es definitiv nicht für einen ganzen Seitenhintergrund verwenden. Wenn Sie mehr darüber lesen möchten, warum Sie GIFs vermeiden sollten, finden Sie hier eine gute Ressource mit vielen Gründen.

JavaScript ist in diesem Fall definitiv eine Option. Elemente mit einem leicht verschobenen Hintergrund anzeigen oder ausblenden war das Erste, was mir in den Sinn kam, und Canvas könnte auch helfen. All dies schien jedoch für ein einfaches Hintergrundbild ein wenig übertrieben. Ich entschied mich für einen reinen CSS-Ansatz.

Meine Lösung war, ein kleines "verrauschtes" PNG-Bild als background-image zu verwenden, background-repeat zu aktivieren und es über einen einfarbigen Hintergrund zu legen. Wie habe ich den Rauscheffekt erzielt? Mit unendlicher CSS-Animation! Indem ich background-position über einen Zeitraum von 200 Millisekunden auf unterschiedliche Werte gesetzt habe. So sah das Ergebnis aus

Siehe den Pen MXoddr von Georgy Marchuk (@gmrchk) auf CodePen.

Können Sie das Problem erraten? Für mich schien es eine ziemlich elegante Lösung zu sein, und ich war begeistert, es ohne ein schrottiges GIF und nicht einmal mit einer einzigen Zeile JavaScript geschafft zu haben. Nur einfaches CSS, das heutzutage in Browsern optimiert ist.

Nun, das Paint Flashing zeigte etwas ganz anderes. Die Schicht in Fenstergröße wurde ständig neu gezeichnet, ohne dass der Benutzer etwas tat. Sie können das Paint Flashing in der obigen Demo sehen, wenn Sie es im Render-Panel aktivieren (beachten Sie, dass Paint Flashing in eingebetteten Pens nicht angezeigt wird).

Ohne Paint Flashing (links) vs. mit Paint Flashing (rechts)

Das verträgt sich sicherlich nicht gut mit der Leistung der Website und saugt Laptop-Akkus aus, als gäbe es kein Morgen.

CPU-Auslastung für die Animation mit background-position (oben) und transform (unten)

Diese gesamte CPU-Auslastung hätte vermieden werden können, indem die Änderungen an background-position durch transform oder opacity ersetzt worden wären.

Siehe den Pen XYOYGm von Georgy Marchuk (@gmrchk) auf CodePen.

Das Problem

Ich mache schon eine Weile Webentwicklung und wusste sehr gut, dass das Animieren eines Hintergrunds nie eine gute Idee ist. Das fühlte sich wie ein Anfängerfehler an. Menschen machen Fehler… aber das ist nicht die ganze Geschichte. Die Website war träge und unangenehm zu navigieren. Wie konnte ich das übersehen?

Etwas, das sicherlich eine große Rolle spielt, ist die Tatsache, dass ich (und Sie vielleicht auch) ein wenig verwöhnt bin, was die Entwicklungsausrüstung angeht. Ich habe einen schönen, leistungsstarken Computer für die Arbeit und schnellen Internetzugang. Solange wir keinen wirklich schlechten Code schreiben, läuft alles ziemlich reibungslos in unseren Augen. Aber das ist nicht immer der Fall für unsere Benutzer.

Ein ähnliches Problem gilt für viele andere Dinge – wie die Bildschirmgröße. Wenn wir mit einer Übertreibung auf einem 27-Zoll-Display mit 4K-Auflösung entwickeln und die Designs hauptsächlich für 1920×1080 erhalten, kommen unsere Besucher hauptsächlich von 1366×768 Laptops und haben einen völlig anderen Workflow, wenn es um die Nutzung eines Computers geht.

Fazit

Obwohl dieser Artikel als Stück über Painting begann, geht es im Grunde viel mehr darum, sich des Einflusses bewusst zu sein, den unser Code auf den Malprozess oder die allgemeine Leistung hat. Während Painting ein gutes Beispiel für etwas ist, das problematisch und leicht zu übersehen sein kann, ist das Problem eher eine Diskrepanz zwischen Entwickler und Benutzer.

Das Web ist ein Ort vieler Umgebungen, in denen die Umgebung des Entwicklers oft weit von der des Benutzers entfernt ist. Auch wenn wir unsere Arbeitsweise nicht ändern oder zu langsamen Computern wechseln müssen, hilft es definitiv, unsere Arbeit ab und zu so zu sehen, wie sie von anderen gesehen wird. Mein Vorschlag: Wenn Sie nach Hause kommen und etwas Freizeit haben, nehmen Sie Ihren alten Computer und überprüfen Sie Ihre Arbeit dort, um dem näher zu kommen, was Ihre Benutzer erleben.

Wenn Sie keinen solchen Computer zur Verfügung haben, können Werkzeuge wie das Render-Panel sehr nützlich sein.