Front-End-Leistung 2021: Bereitstellungsoptimierungen

Veröffentlicht: 2022-03-10
Kurze Zusammenfassung ↬ Machen wir 2021 … schnell! Eine jährliche Front-End-Performance-Checkliste mit allem, was Sie wissen müssen, um heute schnelle Erfahrungen im Web zu erstellen, von Metriken über Tools bis hin zu Front-End-Techniken. Aktualisiert seit 2016.

Inhaltsverzeichnis

  1. Vorbereitung: Planung und Metriken
  2. Realistische Ziele setzen
  3. Die Umgebung definieren
  4. Asset-Optimierungen
  5. Build-Optimierungen
  6. Lieferoptimierungen
  7. Netzwerk, HTTP/2, HTTP/3
  8. Testen und Überwachen
  9. Schnelle Gewinne
  10. Alles auf einer Seite
  11. Checkliste herunterladen (PDF, Apple Pages, MS Word)
  12. Abonnieren Sie unseren E-Mail-Newsletter, um die nächsten Anleitungen nicht zu verpassen.

Lieferoptimierungen

  1. Verwenden wir defer , um kritisches JavaScript asynchron zu laden?
    Wenn der Benutzer eine Seite anfordert, ruft der Browser den HTML-Code ab und erstellt das DOM, ruft dann das CSS ab und erstellt das CSSOM und generiert dann einen Rendering-Baum, indem er das DOM und das CSSOM abgleicht. Wenn irgendein JavaScript aufgelöst werden muss, beginnt der Browser nicht mit dem Rendern der Seite , bis es aufgelöst ist, wodurch das Rendern verzögert wird. Als Entwickler müssen wir dem Browser explizit mitteilen, dass er nicht warten und mit dem Rendern der Seite beginnen soll. Bei Skripten erreichen Sie dies mit den Attributen defer und async in HTML.

    In der Praxis stellt sich heraus, dass es besser ist, defer statt async zu verwenden. Ah, wo ist nochmal der Unterschied ? Laut Steve async werden asynchrone Skripte sofort ausgeführt, sobald sie ankommen – sobald das Skript fertig ist. Wenn das sehr schnell passiert, zum Beispiel wenn sich das Skript bereits im Cache befindet, kann es tatsächlich den HTML-Parser blockieren. Mit defer führt der Browser keine Skripts aus, bis HTML analysiert wurde. Daher ist es besser, defer zu verwenden, es sei denn, Sie müssen JavaScript ausführen, bevor Sie mit dem Rendern beginnen. Außerdem werden mehrere asynchrone Dateien in einer nicht deterministischen Reihenfolge ausgeführt.

    Es ist erwähnenswert, dass es einige Missverständnisse über async und defer gibt. Am wichtigsten ist, dass async nicht bedeutet, dass der Code ausgeführt wird, wenn das Skript bereit ist; es bedeutet, dass es immer dann ausgeführt wird, wenn das Skript bereit ist und alle vorherigen Synchronisierungsarbeiten abgeschlossen sind. Mit den Worten von Harry Roberts: „Wenn Sie ein async Skript nach Synchronisierungsskripts einfügen, ist Ihr async Skript nur so schnell wie Ihr langsamstes Synchronisierungsskript.“

    Außerdem wird nicht empfohlen, sowohl async als auch defer zu verwenden. Moderne Browser unterstützen beides, aber wann immer beide Attribute verwendet werden, gewinnt async immer.

    Wenn Sie mehr ins Detail gehen möchten, hat Milica Mihajlija einen sehr detaillierten Leitfaden zum schnelleren Erstellen des DOM geschrieben, der auf die Details von spekulativem Parsing, Async und Defer eingeht.

  2. Lazy load teure Komponenten mit IntersectionObserver und Prioritätshinweisen.
    Im Allgemeinen wird empfohlen, alle teuren Komponenten wie schweres JavaScript, Videos, iFrames, Widgets und möglicherweise Bilder träge zu laden. Natives Lazy-Loading ist bereits für Bilder und Iframes mit dem loading Attribut verfügbar (nur Chromium). Unter der Haube verschiebt dieses Attribut das Laden der Ressource, bis sie eine berechnete Entfernung vom Darstellungsbereich erreicht.
    <!-- Lazy loading for images, iframes, scripts. Probably for images outside of the viewport. --> <img loading="lazy" ... /> <iframe loading="lazy" ... /> <!-- Prompt an early download of an asset. For critical images, eg hero images. --> <img loading="eager" ... /> <iframe loading="eager" ... />

    Dieser Schwellenwert hängt von einigen Dingen ab, von der Art der abgerufenen Bildressource bis zum effektiven Verbindungstyp. Experimente, die mit Chrome auf Android durchgeführt wurden, deuten jedoch darauf hin, dass auf 4G 97,5 % der Bilder, die unter der Falte liegen und Lazy-Loaded sind, innerhalb von 10 ms, nachdem sie sichtbar wurden, vollständig geladen wurden, also sollte es sicher sein.

    Wir können auch das importance ( high oder low ) für ein <script> -, <img> - oder <link> -Element (nur Blink) verwenden. Tatsächlich ist es eine großartige Möglichkeit, Bilder in Karussells zu depriorisieren und Skripts neu zu priorisieren. Manchmal benötigen wir jedoch möglicherweise eine etwas detailliertere Steuerung.

    <!-- When the browser assigns "High" priority to an image, but we don't actually want that. --> <img src="less-important-image.svg" importance="low" ... /> <!-- We want to initiate an early fetch for a resource, but also deprioritize it. --> <link rel="preload" importance="low" href="/script.js" as="script" />

    Die leistungsstärkste Methode für etwas ausgefeilteres verzögertes Laden ist die Verwendung der Intersection Observer-API, die eine Möglichkeit bietet , Änderungen an der Überschneidung eines Zielelements mit einem übergeordneten Element oder mit dem Ansichtsfenster eines Dokuments der obersten Ebene asynchron zu beobachten . Grundsätzlich müssen Sie ein neues IntersectionObserver -Objekt erstellen, das eine Callback-Funktion und eine Reihe von Optionen erhält. Dann fügen wir ein zu beobachtendes Ziel hinzu.

    Die Callback-Funktion wird ausgeführt, wenn das Ziel sichtbar oder unsichtbar wird. Wenn sie also den Ansichtsbereich abfängt, können Sie einige Aktionen ausführen, bevor das Element sichtbar wird. Tatsächlich haben wir eine granulare Kontrolle darüber, wann der Rückruf des Beobachters aufgerufen werden soll, mit rootMargin (Rand um die Wurzel) und threshold (eine einzelne Zahl oder ein Array von Zahlen, die angeben, auf welchen Prozentsatz der Sichtbarkeit des Ziels wir abzielen).

    Alejandro Garcia Anglada hat ein praktisches Tutorial veröffentlicht, wie man es tatsächlich implementiert, Rahul Nanwani schrieb einen ausführlichen Beitrag über das verzögerte Laden von Vorder- und Hintergrundbildern, und Google Fundamentals bietet ebenfalls ein detailliertes Tutorial über das verzögerte Laden von Bildern und Videos mit Intersection Observer.

    Erinnern Sie sich an kunstgesteuertes Geschichtenerzählen mit langen Lesevorgängen mit sich bewegenden und klebrigen Objekten? Auch mit Intersection Observer lässt sich performantes Scrollytelling realisieren.

    Überprüfen Sie noch einmal, was Sie sonst noch faul laden könnten. Sogar Lazy-Loading-Übersetzungsstrings und Emojis könnten helfen. Auf diese Weise gelang es Mobile Twitter, eine 80 % schnellere JavaScript-Ausführung aus der neuen Internationalisierungspipeline zu erreichen.

    Ein kurzes Wort der Vorsicht: Es ist erwähnenswert, dass Lazy Loading eher eine Ausnahme als die Regel sein sollte. Es ist wahrscheinlich nicht sinnvoll, irgendetwas träge zu laden, was die Leute tatsächlich schnell sehen sollen, z. B. Produktseitenbilder, Heldenbilder oder ein Skript, das erforderlich ist, damit die Hauptnavigation interaktiv wird.

Ein Beispiel, das einen alten Schwellenwert von 3000 Pixeln mit 160 KB Downloads (links) zeigt, während der neue Schwellenwert einen Betrag von 1250 Pixeln mit nur 90 KB Downloads (rechts) hat, was eine Verbesserung der Einsparungen beim Laden von img-Lazy-Daten zeigt
Bei schnellen Verbindungen (z. B. 4G) wurde der Schwellenwert für die Entfernung vom Darstellungsbereich von Chrome kürzlich von 3000 Pixel auf 1250 Pixel verringert, und bei langsameren Verbindungen (z. B. 3G) wurde der Schwellenwert von 4000 Pixel auf 2500 Pixel geändert. (Große Vorschau)
Eine Illustration mit Text um ein Mobiltelefon herum, auf der die Twitter-Benutzeroberfläche gezeigt wird und die Werkzeugverbesserungen von Lazy-Load-Übersetzungszeichenfolgen erklärt
Durch verzögertes Laden von Übersetzungszeichenfolgen gelang es Mobile Twitter, eine 80 % schnellere JavaScript-Ausführung aus der neuen Internationalisierungspipeline zu erreichen. (Bildnachweis: Addy Osmani) (Große Vorschau)
  1. Bilder nach und nach laden.
    Sie könnten sogar Lazy Loading auf die nächste Stufe heben, indem Sie Ihren Seiten progressives Laden von Bildern hinzufügen. Ähnlich wie bei Facebook, Pinterest, Medium und Wolt könnten Sie zuerst Bilder mit niedriger Qualität oder sogar verschwommen laden und sie dann, während die Seite weiter geladen wird, durch die Versionen in voller Qualität ersetzen, indem Sie die BlurHash-Technik oder LQIP (Low Quality Image Placeholders) verwenden. Technik.

    Die Meinungen gehen auseinander, ob diese Techniken die Benutzererfahrung verbessern oder nicht, aber es verbessert definitiv die Zeit bis zum First Contentful Paint. Wir können es sogar automatisieren, indem wir SQIP verwenden, das eine Version eines Bildes mit niedriger Qualität als SVG-Platzhalter oder Gradient Image Placeholders mit linearen CSS-Verläufen erstellt.

    Diese Platzhalter könnten in HTML eingebettet werden, da sie sich natürlich gut mit Textkomprimierungsmethoden komprimieren lassen. Dean Hume hat in seinem Artikel beschrieben, wie diese Technik mit Intersection Observer implementiert werden kann.

    Zurückfallen? Wenn der Browser den Schnittmengenbeobachter nicht unterstützt, können wir immer noch ein Polyfill laden oder die Bilder sofort laden. Und es gibt sogar eine Bibliothek dafür.

    Willst du schicker werden? Sie könnten Ihre Bilder nachzeichnen und primitive Formen und Kanten verwenden, um einen einfachen SVG-Platzhalter zu erstellen, ihn zuerst zu laden und dann vom Platzhalter-Vektorbild zum (geladenen) Bitmap-Bild überzugehen.

  2. Drei verschiedene Versionen, die die SVG-Lazy-Loading-Technik von Jose M. Perez zeigen, eine Version ähnlich der Kubismus-Kunst auf der linken Seite, eine verpixelte unscharfe Version in der Mitte und ein richtiges Bild von Jose selbst auf der rechten Seite
    SVG-Lazy-Loading-Technik von Jose M. Perez. (Große Vorschau)
  3. Verzögern Sie das Rendern mit content-visibility ?
    Bei einem komplexen Layout mit vielen Inhaltsblöcken, Bildern und Videos kann das Decodieren von Daten und das Rendern von Pixeln ein ziemlich teurer Vorgang sein – insbesondere auf Low-End-Geräten. Mit content-visibility: auto können wir den Browser auffordern, das Layout der untergeordneten Elemente zu überspringen, während sich der Container außerhalb des Ansichtsfensters befindet.

    Beispielsweise könnten Sie das Rendern der Fußzeile und der späten Abschnitte beim anfänglichen Laden überspringen:

    footer { content-visibility: auto; contain-intrinsic-size: 1000px; /* 1000px is an estimated height for sections that are not rendered yet. */ }

    Beachten Sie, dass content-visibility: auto; verhält sich wie overflow: hidden; , aber Sie können es beheben, indem Sie padding-left und padding-right anstelle des standardmäßigen margin-left: auto; , margin-right: auto; und eine deklarierte Breite. Das Padding ermöglicht grundsätzlich, dass Elemente die Content-Box überlaufen und in die Padding-Box eintreten, ohne das Box-Modell als Ganzes zu verlassen und abgeschnitten zu werden.

    Denken Sie auch daran, dass Sie einige CLS einführen könnten, wenn neuer Inhalt schließlich gerendert wird, daher ist es eine gute Idee, " contain-intrinsic-size " mit einem Platzhalter in der richtigen Größe zu verwenden ( danke, Una! ).

    Thijs Terluin hat viel mehr Details über beide Eigenschaften und wie contain-intrinsic-size Eigengröße vom Browser berechnet wird, Malte Ubl zeigt, wie Sie sie berechnen können, und ein kurzes Erklärvideo von Jake und Surma erklärt, wie das alles funktioniert.

    Und wenn Sie etwas detaillierter werden müssen, können Sie mit CSS Containment Layout-, Stil- und Malarbeiten für Nachkommen eines DOM-Knotens manuell überspringen, wenn Sie nur Größe, Ausrichtung oder berechnete Stile für andere Elemente benötigen – oder das Element gerade ist außerhalb der Leinwand.

Die Renderleistung beim anfänglichen Laden beträgt 2.288 ms für Baseline (links) und 13.464 ms für Chunks mit content-visibility:auto (rechts).
In der Demo führt das Anwenden von content-visibility: auto auf aufgeteilte Inhaltsbereiche zu einer 7-fachen Steigerung der Renderleistung beim anfänglichen Laden. (Große Vorschau)
  1. Verzögern Sie die Dekodierung mit decoding="async" ?
    Manchmal erscheinen Inhalte außerhalb des Bildschirms, aber wir möchten sicherstellen, dass sie verfügbar sind, wenn Kunden sie brauchen – idealerweise nichts im kritischen Pfad blockieren, sondern asynchron decodieren und rendern. Wir können decoding="async" , um dem Browser die Erlaubnis zu erteilen, das Bild aus dem Haupt-Thread zu dekodieren, wodurch eine Auswirkung der CPU-Zeit auf den Benutzer vermieden wird, die zum Dekodieren des Bildes verwendet wird (über Malte Ubl):

    <img decoding="async" … />

    Alternativ können wir für Offscreen-Bilder zuerst einen Platzhalter anzeigen und, wenn sich das Bild im Ansichtsfenster befindet, mit IntersectionObserver einen Netzwerkaufruf auslösen, damit das Bild im Hintergrund heruntergeladen wird. Außerdem können wir das Rendern bis zum Decodieren mit img.decode() verschieben oder das Bild herunterladen, wenn die Image Decode API nicht verfügbar ist.

    Beim Rendern des Bildes können wir beispielsweise Einblendanimationen verwenden. Katie Hempenius und Addy Osmani teilen weitere Einblicke in ihrem Vortrag Speed ​​at Scale: Web Performance Tips and Tricks from the Trenches.

  2. Generieren und bedienen Sie kritisches CSS?
    Um sicherzustellen, dass Browser so schnell wie möglich mit dem Rendern Ihrer Seite beginnen, ist es üblich geworden, alle CSS zu sammeln, die erforderlich sind, um mit dem Rendern des ersten sichtbaren Teils der Seite zu beginnen (bekannt als „Critical CSS“ oder „Above-the-Fold-CSS“. ") und fügen Sie es inline in den <head> der Seite ein, wodurch Roundtrips reduziert werden. Aufgrund der begrenzten Größe der ausgetauschten Pakete während der langsamen Startphase liegt Ihr Budget für kritisches CSS bei etwa 14 KB.

    Wenn Sie darüber hinausgehen, benötigt der Browser zusätzliche Roundtrips, um mehr Stile abzurufen. CriticalCSS und Critical ermöglichen es Ihnen, kritisches CSS für jede von Ihnen verwendete Vorlage auszugeben. Unserer Erfahrung nach war jedoch kein automatisches System besser als die manuelle Sammlung kritischer CSS für jede Vorlage, und tatsächlich ist dies der Ansatz, zu dem wir kürzlich zurückgekehrt sind.

    Sie können dann kritisches CSS einbetten und den Rest mit dem critters Webpack-Plug-in lazy-loaden. Erwägen Sie nach Möglichkeit die Verwendung des von der Filament Group verwendeten bedingten Inlining-Ansatzes oder konvertieren Sie Inline-Code spontan in statische Assets.

    Wenn Sie derzeit Ihr vollständiges CSS asynchron mit Bibliotheken wie loadCSS laden, ist dies nicht wirklich erforderlich. Mit media="print" können Sie den Browser dazu verleiten, das CSS asynchron abzurufen, aber nach dem Laden auf die Bildschirmumgebung anzuwenden. ( Danke Scott! )

    <!-- Via Scott Jehl. https://www.filamentgroup.com/lab/load-css-simpler/ --> <!-- Load CSS asynchronously, with low priority --> <link rel="stylesheet" href="full.css" media="print" onload="this.media='all'" />

    Beim Sammeln aller kritischen CSS für jede Vorlage ist es üblich, nur den „above-the-fold“-Bereich zu erkunden. Bei komplexen Layouts kann es jedoch eine gute Idee sein, auch die Grundlagen des Layouts einzubeziehen, um massive Kosten für Neuberechnungen und Neuzeichnungen zu vermeiden, die Ihrer Core Web Vitals-Punktzahl als Folge schaden würden.

    Was ist, wenn ein Benutzer eine URL erhält, die direkt auf die Mitte der Seite verweist, aber das CSS noch nicht heruntergeladen wurde? Dabei ist es üblich geworden, unkritische Inhalte auszublenden, zB mit opacity: 0; in eingebettetem CSS und opacity: 1 in der vollständigen CSS-Datei und zeigt sie an, wenn CSS verfügbar ist. Es hat jedoch einen großen Nachteil , da Benutzer mit langsamen Verbindungen den Inhalt der Seite möglicherweise nie lesen können. Deshalb ist es besser, den Inhalt immer sichtbar zu halten, auch wenn er vielleicht nicht richtig gestylt ist.

    Kritisches CSS (und andere wichtige Assets) in einer separaten Datei auf der Root-Domain abzulegen, hat aufgrund des Cachings Vorteile, manchmal sogar mehr als Inlining. Chrome öffnet spekulativ eine zweite HTTP-Verbindung zur Stammdomäne, wenn die Seite angefordert wird, wodurch die Notwendigkeit einer TCP-Verbindung zum Abrufen dieses CSS entfällt. Das bedeutet, dass Sie eine Reihe kritischer -CSS-Dateien (z. B. kritische-homepage.css , kritische-produkt-seite.css usw.) erstellen und sie von Ihrem Stammverzeichnis aus bereitstellen könnten, ohne sie inline zu müssen. ( Danke Philipp! )

    Ein Wort der Vorsicht: Mit HTTP/2 könnte kritisches CSS in einer separaten CSS-Datei gespeichert und über einen Server-Push bereitgestellt werden, ohne das HTML aufzublähen. Der Haken ist, dass das Server-Pushing mit vielen Fallstricken und Race-Conditions über Browser hinweg mühsam war. Es wurde nie durchgehend unterstützt und hatte einige Caching-Probleme (siehe Folie 114 ff. der Präsentation von Hooman Beheshti).

    Der Effekt könnte in der Tat negativ sein und die Netzwerkpuffer aufblähen, wodurch verhindert wird, dass echte Frames im Dokument geliefert werden. Daher war es nicht verwunderlich, dass Chrome plant, die Unterstützung für Server Push vorerst zu entfernen.

  3. Experimentieren Sie mit der Neugruppierung Ihrer CSS-Regeln.
    Wir haben uns an kritisches CSS gewöhnt, aber es gibt ein paar Optimierungen, die darüber hinausgehen könnten. Harry Roberts führte eine bemerkenswerte Forschung mit ziemlich überraschenden Ergebnissen durch. Beispielsweise könnte es eine gute Idee sein, die Haupt-CSS-Datei in ihre einzelnen Medienabfragen aufzuteilen. Auf diese Weise ruft der Browser kritisches CSS mit hoher Priorität und alles andere mit niedriger Priorität ab – vollständig abseits des kritischen Pfads.

    Vermeiden Sie es außerdem, <link rel="stylesheet" /> vor async Snippets zu platzieren. Wenn Skripts nicht von Stylesheets abhängen, sollten Sie Blockierungsskripts über Blockierungsstilen platzieren. Wenn dies der Fall ist, teilen Sie dieses JavaScript in zwei Teile und laden Sie es auf beiden Seiten Ihres CSS.

    Scott Jehl löste ein weiteres interessantes Problem, indem er eine Inline-CSS-Datei mit einem Servicemitarbeiter zwischenspeicherte, ein häufiges Problem, das Ihnen bekannt ist, wenn Sie kritisches CSS verwenden. Grundsätzlich fügen wir dem style ein ID-Attribut hinzu, damit es mit JavaScript leicht zu finden ist, dann findet ein kleines Stück JavaScript dieses CSS und verwendet die Cache-API, um es in einem lokalen Browser-Cache zu speichern (mit einem Inhaltstyp von text/css ) zur Verwendung auf nachfolgenden Seiten. Um Inlining auf nachfolgenden Seiten zu vermeiden und stattdessen die zwischengespeicherten Assets extern zu referenzieren, setzen wir dann beim ersten Besuch einer Website ein Cookie. Voila!

    Es ist erwähnenswert, dass dynamisches Styling auch teuer sein kann, aber normalerweise nur in Fällen, in denen Sie sich auf Hunderte von gleichzeitig gerenderten zusammengesetzten Komponenten verlassen. Wenn Sie also CSS-in-JS verwenden, stellen Sie sicher, dass Ihre CSS-in-JS-Bibliothek die Ausführung optimiert, wenn Ihr CSS keine Abhängigkeiten von Design oder Requisiten aufweist, und überkomponieren Sie keine formatierten Komponenten . Aggelos Arvanitakis gibt weitere Einblicke in die Leistungskosten von CSS-in-JS.

  4. Streamen Sie Antworten?
    Streams werden oft vergessen und vernachlässigt und bieten eine Schnittstelle zum Lesen oder Schreiben asynchroner Datenblöcke, von denen zu einem bestimmten Zeitpunkt möglicherweise nur eine Teilmenge im Speicher verfügbar ist. Grundsätzlich erlauben sie der Seite, die die ursprüngliche Anfrage gestellt hat, mit der Arbeit an der Antwort zu beginnen, sobald der erste Datenblock verfügbar ist, und verwenden Parser, die für das Streaming optimiert sind, um den Inhalt nach und nach anzuzeigen.

    Wir könnten einen Stream aus mehreren Quellen erstellen. Anstatt beispielsweise eine leere UI-Shell bereitzustellen und sie von JavaScript füllen zu lassen, können Sie den Service-Worker einen Stream erstellen lassen, bei dem die Shell aus einem Cache stammt, der Text jedoch aus dem Netzwerk. Wie Jeff Posnick bemerkte, wenn Ihre Web-App von einem CMS unterstützt wird, das HTML durch Zusammenfügen von Teilvorlagen auf dem Server rendert, wird dieses Modell direkt in die Verwendung von Streaming-Antworten übersetzt, wobei die Vorlagenlogik im Service-Worker statt auf Ihrem Server repliziert wird. Der Artikel The Year of Web Streams von Jake Archibald hebt hervor, wie genau man es aufbauen könnte. Der Leistungsschub ist deutlich spürbar.

    Ein wichtiger Vorteil des Streamens der gesamten HTML-Antwort besteht darin, dass HTML, das während der anfänglichen Navigationsanforderung gerendert wird, den Streaming-HTML-Parser des Browsers voll ausnutzen kann. HTML-Blöcke, die nach dem Laden der Seite in ein Dokument eingefügt werden (wie es bei Inhalten üblich ist, die über JavaScript gefüllt werden), können diese Optimierung nicht nutzen.

    Browserunterstützung? Immer noch auf dem Weg dorthin mit teilweiser Unterstützung in Chrome, Firefox, Safari und Edge, die die API und Service Workers unterstützen, die in allen modernen Browsern unterstützt werden. Und wenn Sie wieder abenteuerlustig sind, können Sie eine experimentelle Implementierung von Streaming-Anfragen testen, die es Ihnen ermöglicht, mit dem Senden der Anfrage zu beginnen, während Sie noch den Text generieren. Verfügbar in Chrome 85.

Ein Bild, das die Speicherdatennutzung auf Android Chrome und die durchschnittlichen img-Hits oder -Sitzungen zusammenfasst, die von Cloudinary Research im November 2019 und April 2020 entdeckt wurden
Laut einer Studie von Cloudinary haben 18 % der globalen Android-Chrome-Benutzer den Lite-Modus (auch bekannt als Save-Data) aktiviert. (Große Vorschau)
  1. Erwägen Sie, Ihre Komponenten verbindungsbewusst zu machen.
    Daten können teuer sein, und mit wachsender Nutzlast müssen wir Benutzer respektieren, die sich für Dateneinsparungen entscheiden, während sie auf unsere Websites oder Apps zugreifen. Der Clienthinweis-Anforderungsheader von Save-Data ermöglicht es uns, die Anwendung und die Nutzlast für Benutzer mit eingeschränkten Kosten und Leistung anzupassen.

    Tatsächlich könnten Sie Anforderungen für Bilder mit hoher DPI in Bilder mit niedriger DPI umschreiben, Webschriftarten entfernen, ausgefallene Parallaxeneffekte, Miniaturansichten in der Vorschau anzeigen und unendlich scrollen, die automatische Wiedergabe von Videos deaktivieren, Server-Pushs deaktivieren, die Anzahl der angezeigten Elemente reduzieren und die Bildqualität herabstufen oder Sie können sogar ändern, wie Sie Markup bereitstellen. Tim Vereecke hat einen sehr ausführlichen Artikel über Data-S(h)aver-Strategien mit vielen Optionen zur Datenspeicherung veröffentlicht.

    Wer nutzt save-data , fragen Sie sich vielleicht? 18 % der weltweiten Android-Chrome-Nutzer haben den Lite-Modus aktiviert (mit aktiviertem Save-Data ), und die Zahl dürfte höher sein. Laut den Untersuchungen von Simon Hearne ist die Opt-in-Rate auf billigeren Geräten am höchsten, aber es gibt viele Ausreißer. Zum Beispiel: Benutzer in Kanada haben eine Opt-in-Rate von über 34 % (im Vergleich zu ~ 7 % in den USA) und Benutzer des neuesten Samsung-Flaggschiffs haben eine Opt-in-Rate von fast 18 % weltweit.

    Wenn der Datenspeichermodus aktiviert ist, bietet Chrome Mobile ein optimiertes Erlebnis, dh ein Proxy- Save-Data mit zurückgestellten Skripten , erzwungener font-display: swap und erzwungenem Lazy Loading. Es ist einfach sinnvoller, das Erlebnis selbst aufzubauen, anstatt sich auf den Browser zu verlassen, um diese Optimierungen vorzunehmen.

    Der Header wird derzeit nur in Chromium, in der Android-Version von Chrome oder über die Data Saver-Erweiterung auf einem Desktop-Gerät unterstützt. Schließlich können Sie die Netzwerkinformations-API auch verwenden, um kostspielige JavaScript-Module, hochauflösende Bilder und Videos basierend auf dem Netzwerktyp bereitzustellen. Die Network Information API und insbesondere navigator.connection.effectiveType . EffectiveType verwenden RTT , downlink , effectiveType -Werte (und einige andere), um eine Darstellung der Verbindung und der Daten bereitzustellen, die Benutzer verarbeiten können.

    Max Bock spricht in diesem Zusammenhang von Connection-Aware Components und Addy Osmani von Adaptive Module Serving. Beispielsweise könnten wir mit React eine Komponente schreiben, die für verschiedene Verbindungstypen unterschiedlich rendert. Wie Max vorgeschlagen hat, könnte eine <Media /> -Komponente in einem Nachrichtenartikel Folgendes ausgeben:

    • Offline : ein Platzhalter mit alt -Text,
    • 2G / save-data Modus: ein Bild mit niedriger Auflösung,
    • 3G auf Nicht-Retina-Bildschirm: ein Bild mit mittlerer Auflösung,
    • 3G auf Retina-Bildschirmen: hochauflösendes Retina-Bild,
    • 4G : ein HD-Video.

    Dean Hume bietet eine praktische Implementierung einer ähnlichen Logik unter Verwendung eines Servicemitarbeiters. Für ein Video könnten wir standardmäßig ein Videoposter anzeigen und dann bei besseren Verbindungen das "Play"-Symbol sowie die Videoplayer-Shell, Metadaten des Videos usw. anzeigen. Als Fallback für nicht unterstützende Browser könnten wir auf das canplaythrough Ereignis lauschen und Promise.race() verwenden, um das Laden der Quelle zu verzögern, wenn das canplaythrough Ereignis nicht innerhalb von 2 Sekunden ausgelöst wird.

    Wenn Sie etwas tiefer eintauchen möchten, finden Sie hier ein paar Ressourcen für den Einstieg:

    • Addy Osmani zeigt, wie man adaptives Serving in React implementiert.
    • React Adaptive Loading Hooks & Utilities bietet Codeschnipsel für React,
    • Netanel Basel untersucht verbindungsbewusste Komponenten in Angular,
    • Theodore Vorilas teilt mit, wie das Bereitstellen adaptiver Komponenten mithilfe der Netzwerkinformations-API in Vue funktioniert.
    • Umar Hansa zeigt, wie man teures JavaScript selektiv herunterlädt/ausführt.
  2. Erwägen Sie, Ihre Komponenten gerätespeicherfähig zu machen.
    Die Netzwerkverbindung gibt uns jedoch nur eine Perspektive auf den Kontext des Benutzers. Darüber hinaus könnten Sie mit der Device Memory API auch Ressourcen basierend auf dem verfügbaren Gerätespeicher dynamisch anpassen. navigator.deviceMemory gibt zurück, wie viel RAM das Gerät in Gigabyte hat, abgerundet auf die nächste Zweierpotenz. Die API verfügt auch über einen Client-Hinweis-Header, Device-Memory , der denselben Wert meldet.

    Bonus : Umar Hansa zeigt, wie man teure Skripte mit dynamischen Importen aufschiebt, um die Erfahrung basierend auf Gerätespeicher, Netzwerkkonnektivität und Hardware-Parallelität zu ändern.

Eine Aufschlüsselung, die zeigt, wie verschiedene Ressourcen in Blink ab Chrome 46 und höher priorisiert werden
Eine Aufschlüsselung, die zeigt, wie verschiedene Ressourcen in Blink ab Chrome 46 und höher priorisiert werden. (Bildnachweis: Addy Osmani) (Große Vorschau)
  1. Wärmen Sie die Verbindung auf, um die Lieferung zu beschleunigen.
    Verwenden Sie Ressourcenhinweise, um Zeit zu sparen bei dns-prefetch (der eine DNS-Suche im Hintergrund durchführt), preconnect (der den Browser auffordert, den Verbindungs-Handshake (DNS, TCP, TLS) im Hintergrund zu starten), prefetch (der den Browser fragt um eine Ressource anzufordern) und preload (was unter anderem Ressourcen vorab abruft, ohne sie auszuführen). Gut unterstützt in modernen Browsern, mit baldiger Unterstützung für Firefox.

    Erinnerst du dich an prerender ? Der Ressourcenhinweis, der verwendet wird, um den Browser aufzufordern, die gesamte Seite für die nächste Navigation im Hintergrund aufzubauen. Die Implementierungsprobleme waren ziemlich problematisch und reichten von einem enormen Speicherbedarf und Bandbreitenverbrauch bis hin zu mehreren registrierten Analysetreffern und Anzeigenimpressionen.

    Es überrascht nicht, dass es veraltet war, aber das Chrome-Team hat es als NoState-Prefetch-Mechanismus zurückgebracht. Tatsächlich behandelt Chrome den prerender Hinweis stattdessen als NoState Prefetch, sodass wir ihn heute noch verwenden können. Wie Katie Hempenius in diesem Artikel erklärt, „ruft NoState Prefetch wie beim Prerendering Ressourcen im Voraus ab , aber im Gegensatz zum Prerendering führt es kein JavaScript aus und rendert keinen Teil der Seite im Voraus.“

    NoState Prefetch verwendet nur ~45 MB Arbeitsspeicher und abgerufene Unterressourcen werden mit einer IDLE -Netzpriorität abgerufen. Seit Chrome 69 fügt NoState Prefetch allen Anfragen den Header Purpose: Prefetch hinzu, um sie vom normalen Surfen unterscheidbar zu machen.

    Achten Sie auch auf Prerendering-Alternativen und -Portale, eine neue Anstrengung in Richtung datenschutzbewusstes Prerendering, das die eingefügte preview des Inhalts für nahtlose Navigationen bereitstellt.

    Die Verwendung von Ressourcenhinweisen ist wahrscheinlich der einfachste Weg, um die Leistung zu steigern , und es funktioniert tatsächlich gut. Wann was verwenden? Wie Addy Osmani erklärt hat, ist es sinnvoll, Ressourcen vorab zu laden, von denen wir wissen, dass sie sehr wahrscheinlich auf der aktuellen Seite und für zukünftige Navigationen über mehrere Navigationsgrenzen hinweg verwendet werden, z. B. Webpack-Pakete, die für Seiten benötigt werden, die der Benutzer noch nicht besucht hat.

    Addys Artikel über „Loading Priorities in Chrome“ zeigt, wie genau Chrome Ressourcenhinweise interpretiert. Wenn Sie also entschieden haben, welche Assets für das Rendern wichtig sind, können Sie ihnen eine hohe Priorität zuweisen. Um zu sehen, wie Ihre Anfragen priorisiert werden, können Sie eine „Prioritäts“-Spalte in der Chrome DevTools-Netzwerkanfragetabelle (sowie in Safari) aktivieren.

    Heutzutage verwenden wir meistens zumindest preconnect und dns-prefetch , und wir werden vorsichtig sein, wenn wir prefetch , preload und prerender . Beachten Sie, dass selbst bei preconnect und dns-prefetch der Browser eine Begrenzung für die Anzahl der Hosts hat, die er parallel nachschlagen/verbinden wird, daher ist es eine sichere Sache, sie nach Priorität zu ordnen ( danke Philip Tellis! ).

    Da Schriftarten normalerweise wichtige Elemente auf einer Seite sind, ist es manchmal eine gute Idee, den Browser aufzufordern, kritische Schriftarten mit preload herunterzuladen. Überprüfen Sie jedoch noch einmal, ob dies tatsächlich der Leistung zugute kommt, da es beim Vorladen von Schriftarten ein Rätsel der Prioritäten gibt: Da das preload als sehr wichtig angesehen wird, kann es sogar noch kritischere Ressourcen wie kritisches CSS überspringen. ( Danke Barry! )

    <!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />
    <!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />

    Da <link rel="preload"> ein media akzeptiert, könnten Sie sich dafür entscheiden, Ressourcen basierend auf @media selektiv herunterzuladen, wie oben gezeigt.

    Darüber hinaus können wir die Attribute imagesrcset und imagesizes verwenden, um spät entdeckte Heldenbilder oder Bilder, die über JavaScript geladen werden, schneller vorzuladen, z. B. Filmplakate:

    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>
    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>

    Wir können den JSON auch als fetch vorladen , sodass er erkannt wird, bevor JavaScript ihn anfordern kann:

    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="fetch" href="foo.com/api/movies.json" crossorigin>

    Wir könnten JavaScript auch dynamisch laden, effektiv für eine verzögerte Ausführung des Skripts.

    /* Adding a preload hint to the head */ var preload = document.createElement("link"); link.href = "myscript.js"; link.rel = "preload"; link.as = "script"; document.head.appendChild(link); /* Injecting a script when we want it to execute */ var script = document.createElement("script"); script.src = "myscript.js"; document.body.appendChild(script);

    Ein paar Fallstricke, die Sie im Hinterkopf behalten sollten: Das preload ist gut, um die Startzeit des Downloads eines Assets näher an die ursprüngliche Anfrage zu verschieben, aber vorgeladene Assets landen im Speicher-Cache , der an die Seite gebunden ist, die die Anfrage stellt. preload spielt gut mit dem HTTP-Cache: Eine Netzwerkanfrage wird nie gesendet, wenn das Element bereits im HTTP-Cache vorhanden ist.

    Daher ist es nützlich für spät entdeckte Ressourcen, Hero-Bilder, die über background-image geladen werden, wichtiges CSS (oder JavaScript) inlinieren und den Rest des CSS (oder JavaScript) vorab laden.

    Ein Beispiel mit dem Cover des Greyhound-Films mit Tom Hanks in der Hauptrolle, um zu zeigen, dass vorinstallierte Bilder früher geladen werden, da nicht auf die Erkennung durch JavaScript gewartet werden muss
    Wichtige Bilder frühzeitig vorladen; Sie müssen nicht auf JavaScript warten, um sie zu entdecken. (Bildnachweis: „Preload Late-Discovered Hero Images Faster“ von Addy Osmani) (Große Vorschau)

    Ein preload -Tag kann ein Preload erst initiieren, nachdem der Browser das HTML vom Server empfangen hat und der Lookahead-Parser das preload -Tag gefunden hat. Das Vorladen über den HTTP-Header könnte etwas schneller sein, da wir nicht darauf warten müssen, dass der Browser den HTML-Code analysiert, um die Anfrage zu starten (es wird jedoch diskutiert).

    Frühe Hinweise werden noch weiter helfen, indem sie das Vorladen ermöglichen, noch bevor die Antwortheader für den HTML-Code gesendet werden (auf der Roadmap in Chromium, Firefox). Außerdem helfen uns Prioritätshinweise dabei, Ladeprioritäten für Skripte anzuzeigen.

    Achtung : Wenn Sie preload verwenden, muss es as definiert werden oder es wird nichts geladen, und vorgeladene Schriftarten ohne das crossorigin Attribut werden doppelt abgerufen. Wenn Sie prefetch verwenden, achten Sie auf die Age Header-Probleme in Firefox.

Ein Diagramm, das die erste zufriedene Farbe (nach Server-Worker-Status) mit einer Anzahl von 0 bis 150 über einen bestimmten Zeitraum (in ms) zeigt
Mit einem Servicemitarbeiter können wir nur das Nötigste an Daten anfordern und diese Daten dann in ein vollständiges HTML-Dokument umwandeln, um FCP zu verbessern. (über Phil Walton) (Große Vorschau)
  1. Verwenden Sie Service Worker für Caching und Netzwerk-Fallbacks.
    Keine Leistungsoptimierung über ein Netzwerk kann schneller sein als ein lokal gespeicherter Cache auf dem Computer eines Benutzers (es gibt jedoch Ausnahmen). Wenn Ihre Website über HTTPS läuft, können wir statische Assets in einem Service-Worker-Cache zwischenspeichern und Offline-Fallbacks (oder sogar Offline-Seiten) speichern und sie vom Computer des Benutzers abrufen, anstatt zum Netzwerk zu gehen.

    Wie von Phil Walton vorgeschlagen, können wir mit Servicemitarbeitern kleinere HTML-Nutzlasten senden, indem wir unsere Antworten programmgesteuert generieren. Ein Servicemitarbeiter kann nur das absolute Minimum an Daten, die er benötigt, vom Server anfordern (z. B. einen Teil des HTML-Inhalts, eine Markdown-Datei, JSON-Daten usw.) und diese Daten dann programmgesteuert in ein vollständiges HTML-Dokument umwandeln . Sobald also ein Benutzer eine Site besucht und der Service Worker installiert ist, wird der Benutzer nie wieder eine vollständige HTML-Seite anfordern. Die Auswirkungen auf die Leistung können ziemlich beeindruckend sein.

    Browserunterstützung? Service-Mitarbeiter werden weitgehend unterstützt und der Fallback ist sowieso das Netzwerk. Hilft es , die Leistung zu steigern ? Oh ja, das tut es. Und es wird immer besser, z. B. mit Background Fetch, das auch Hintergrund-Uploads/Downloads über einen Servicemitarbeiter ermöglicht.

    Es gibt eine Reihe von Anwendungsfällen für einen Servicemitarbeiter. Sie könnten beispielsweise die Funktion „Für Offline speichern“ implementieren, beschädigte Bilder handhaben, Nachrichten zwischen Registerkarten einführen oder verschiedene Caching-Strategien basierend auf Anforderungstypen bereitstellen. Im Allgemeinen besteht eine gängige zuverlässige Strategie darin, die App-Shell im Cache des Servicemitarbeiters zusammen mit einigen kritischen Seiten zu speichern, z. B. Offline-Seite, Titelseite und alles andere, was in Ihrem Fall wichtig sein könnte.

    Es gibt jedoch ein paar Fallstricke zu beachten. Wenn ein Servicemitarbeiter vorhanden ist, müssen wir uns vor Reichweitenanfragen in Safari hüten (wenn Sie Workbox für einen Servicemitarbeiter verwenden, verfügt es über ein Bereichsanfragemodul). Wenn Sie jemals über DOMException: Quota exceeded. Fehler in der Browserkonsole, dann schauen Sie in Gerardos Artikel Wenn 7 KB gleich 7 MB sind.

    Wie Gerardo schreibt: „Wenn Sie eine progressive Web-App erstellen und einen aufgeblähten Cache-Speicher feststellen, wenn Ihr Servicemitarbeiter statische Assets zwischenspeichert, die von CDNs bereitgestellt werden, stellen Sie sicher, dass der richtige CORS-Antwort-Header für ursprungsübergreifende Ressourcen vorhanden ist. Sie speichern keine undurchsichtigen Antworten Mit Ihrem Servicemitarbeiter entscheiden Sie sich unbeabsichtigt für Cross-Origin-Bild-Assets für den CORS-Modus, indem Sie das crossorigin Attribut zum <img> -Tag hinzufügen.“

    Es gibt viele großartige Ressourcen , um mit Servicemitarbeitern zu beginnen:

    • Service Worker Mindset, das Ihnen hilft zu verstehen, wie Servicemitarbeiter hinter den Kulissen arbeiten und was Sie beim Aufbau verstehen müssen.
    • Chris Ferdinandi bietet eine großartige Artikelserie über Servicemitarbeiter, die erklärt, wie Offline-Anwendungen erstellt werden, und eine Vielzahl von Szenarien abdeckt, vom Offline-Speichern kürzlich angesehener Seiten bis zum Festlegen eines Ablaufdatums für Elemente in einem Servicemitarbeiter-Cache.

    • Fallstricke und Best Practices für Servicemitarbeiter, mit einigen Tipps zum Umfang, zur Verzögerung der Registrierung eines Servicemitarbeiters und zum Zwischenspeichern von Servicemitarbeitern.
    • Großartige Serie von Ire Aderinokun über „Offline First“ mit Service Worker, mit einer Strategie zum Precaching der App-Shell.
    • Service Worker: Eine Einführung mit praktischen Tipps zur Verwendung von Service Worker für reichhaltige Offline-Erlebnisse, regelmäßige Hintergrundsynchronisierungen und Push-Benachrichtigungen.
    • Es lohnt sich immer, auf das Offline-Kochbuch des guten alten Jake Archibald mit einer Reihe von Rezepten zum Backen Ihres eigenen Servicemitarbeiters zu verweisen.
    • Workbox ist eine Reihe von Service-Worker-Bibliotheken, die speziell für die Entwicklung progressiver Web-Apps entwickelt wurden.
  2. Führen Sie Server-Worker auf dem CDN/Edge aus, z. B. für A/B-Tests?
    Zu diesem Zeitpunkt sind wir daran gewöhnt, Service Worker auf dem Client auszuführen, aber mit CDNs, die sie auf dem Server implementieren, könnten wir sie auch verwenden, um die Leistung am Edge zu optimieren.

    Wenn beispielsweise HTML in A/B-Tests seinen Inhalt für verschiedene Benutzer variieren muss, könnten wir Service Worker auf den CDN-Servern einsetzen, um die Logik zu handhaben. Wir könnten auch HTML-Rewriting streamen, um Websites zu beschleunigen, die Google Fonts verwenden.

Ein Diagramm, das Zeitreihen von Installationen von Servicemitarbeitern auf Desktops und Mobilgeräten mit dem Prozentsatz der Seiten im Zeitraum zwischen Januar 2016 und Juli 2020 zeigt
Zeitreihen der Installation von Servicemitarbeitern. Laut Web Almanac registrieren nur 0,87 % aller Desktop-Seiten einen Servicemitarbeiter. (Große Vorschau)
  1. Optimieren Sie die Renderleistung.
    Wenn die Anwendung träge ist, macht sich das sofort bemerkbar. Wir müssen also sicherstellen, dass beim Scrollen der Seite oder beim Animieren eines Elements keine Verzögerung auftritt und dass Sie konstant 60 Frames pro Sekunde erreichen. Wenn das nicht möglich ist, dann ist zumindest eine konsistente Bildrate pro Sekunde einem gemischten Bereich von 60 bis 15 vorzuziehen. Verwenden Sie CSS' will-change , um den Browser darüber zu informieren, welche Elemente und Eigenschaften sich ändern.

    Wann immer Sie feststellen, debuggen Sie unnötige Repaints in DevTools:

    • Messen Sie die Laufzeit-Rendering-Leistung. Sehen Sie sich einige nützliche Tipps an, wie Sie es verstehen können.
    • Um loszulegen, lesen Sie den kostenlosen Udacity-Kurs von Paul Lewis zur Browser-Rendering-Optimierung und den Artikel von Georgy Marchuk über Browser-Painting und Überlegungen zur Web-Performance.
    • Aktivieren Sie Paint Flashing in „Weitere Tools → Rendern → Paint Flashing“ in Firefox DevTools.
    • Aktivieren Sie in React DevTools „Updates hervorheben“ und aktivieren Sie „Aufzeichnen, warum jede Komponente gerendert wird“.
    • Sie können auch Why Did You Render verwenden, sodass Sie beim erneuten Rendern einer Komponente durch einen Blitz über die Änderung informiert werden.

    Verwenden Sie ein Mauerwerk-Layout? Denken Sie daran, dass Sie möglicherweise sehr bald ein Mauerwerk-Layout nur mit CSS-Raster erstellen können.

    Wenn Sie tiefer in das Thema eintauchen möchten, hat Nolan Lawson in seinem Artikel Tricks zur genauen Messung der Layoutleistung geteilt, und Jason Miller hat auch alternative Techniken vorgeschlagen. Wir haben auch einen kleinen Artikel von Sergey Chikuyonok darüber, wie man GPU-Animationen richtig macht.

    Hochleistungsanimationen einschließlich Position, Skalierung, Drehung und Deckkraft
    Browser können Transformation und Opazität kostengünstig animieren. CSS-Trigger ist nützlich, um zu überprüfen, ob CSS Re-Layouts oder Reflows auslöst. (Bildnachweis: Addy Osmani) (Große Vorschau)

    Hinweis : Änderungen an GPU-zusammengesetzten Ebenen sind am kostengünstigsten. Wenn Sie also davonkommen, indem Sie nur das Zusammensetzen über opacity und transform auslösen, sind Sie auf dem richtigen Weg. Auch Anna Migas hat in ihrem Vortrag Debugging UI Rendering Performance viele praktische Ratschläge gegeben. Und um zu verstehen, wie die Malleistung in devtools debuggt wird, sehen Sie sich das Auditvideo zur Malleistung von Umar an.

  2. Haben Sie die wahrgenommene Leistung optimiert?
    Während die Reihenfolge, wie Komponenten auf der Seite erscheinen, und die Strategie, wie wir Assets für den Browser bereitstellen, von Bedeutung ist, sollten wir auch die Rolle der wahrgenommenen Leistung nicht unterschätzen. Das Konzept beschäftigt sich mit psychologischen Aspekten des Wartens, im Grunde hält es Kunden beschäftigt oder beschäftigt, während etwas anderes passiert. Hier kommen Wahrnehmungsmanagement, präventiver Start, vorzeitiger Abschluss und Toleranzmanagement ins Spiel.

    Was soll das alles heißen? Beim Laden von Assets können wir versuchen, dem Kunden immer einen Schritt voraus zu sein, sodass sich die Erfahrung schnell anfühlt, während im Hintergrund ziemlich viel passiert. Um den Kunden zu beschäftigen, können wir Skelettbildschirme (Implementierungsdemo) testen, anstatt Indikatoren zu laden, Übergänge/Animationen hinzufügen und die UX im Grunde betrügen, wenn es nichts mehr zu optimieren gibt.

    In ihrer Fallstudie zu The Art of UI Skeletons teilt Kumar McMillan einige Ideen und Techniken zur Simulation dynamischer Listen, Text und des endgültigen Bildschirms sowie zur Berücksichtigung des Skelett-Denkens mit React.

    Beachten Sie jedoch: Skelettbildschirme sollten vor der Bereitstellung getestet werden, da einige Tests gezeigt haben, dass Skelettbildschirme nach allen Metriken am schlechtesten abschneiden können.

  3. Verhindern Sie Layoutverschiebungen und Neulackierungen?
    Im Bereich der wahrgenommenen Leistung ist wahrscheinlich eine der störenderen Erfahrungen Layoutverschiebungen oder Umbrüche , die durch neu skalierte Bilder und Videos, Webschriftarten, eingefügte Anzeigen oder spät entdeckte Skripte verursacht werden, die Komponenten mit tatsächlichen Inhalten füllen. Infolgedessen beginnt ein Kunde möglicherweise mit dem Lesen eines Artikels, nur um durch einen Layoutsprung über dem Lesebereich unterbrochen zu werden. Die Erfahrung ist oft abrupt und ziemlich verwirrend: und das ist wahrscheinlich ein Fall von Ladeprioritäten, die überdacht werden müssen.

    Die Community hat einige Techniken und Workarounds entwickelt, um Reflows zu vermeiden. Im Allgemeinen ist es eine gute Idee, das Einfügen neuer Inhalte über vorhandene Inhalte zu vermeiden , es sei denn, dies geschieht als Reaktion auf eine Benutzerinteraktion. Legen Sie Breiten- und Höhenattribute für Bilder immer fest, sodass moderne Browser das Feld zuweisen und den Platz standardmäßig reservieren (Firefox, Chrome).

    Sowohl für Bilder als auch für Videos können wir einen SVG-Platzhalter verwenden, um das Anzeigefeld zu reservieren, in dem die Medien erscheinen. Das bedeutet, dass der Bereich ordnungsgemäß reserviert wird, wenn Sie auch sein Seitenverhältnis beibehalten müssen. Wir können auch Platzhalter oder Fallback-Bilder für Anzeigen und dynamische Inhalte verwenden sowie Layout-Slots vorab zuweisen.

    Anstatt Bilder mit externen Skripts zu laden, sollten Sie natives Lazy-Loading oder hybrides Lazy-Loading verwenden, wenn wir ein externes Skript nur dann laden, wenn natives Lazy-Loading nicht unterstützt wird.

    Wie oben erwähnt, gruppieren Sie Webfont-Repaints immer und wechseln Sie von allen Fallback-Fonts zu allen Webfonts gleichzeitig – stellen Sie nur sicher, dass dieser Wechsel nicht zu abrupt ist, indem Sie die Zeilenhöhe und den Abstand zwischen den Fonts mit dem Font-Style-Matcher anpassen .

    Um Schriftartmetriken für eine Fallback-Schriftart zu überschreiben , um eine Webschriftart zu emulieren, können wir @font-face-Deskriptoren verwenden, um Schriftartmetriken zu überschreiben (Demo, aktiviert in Chrome 87). (Beachten Sie jedoch, dass Anpassungen bei komplizierten Schriftstapeln kompliziert sind.)

    Für spätes CSS können wir sicherstellen, dass layoutkritisches CSS in den Header jeder Vorlage eingebunden wird . Darüber hinaus: Bei langen Seiten verschiebt der vertikale Scrollbalken den Hauptinhalt um 16 Pixel nach links. Um eine Bildlaufleiste frühzeitig anzuzeigen, können wir overflow-y: scroll on html hinzufügen, um beim ersten Malen eine Bildlaufleiste zu erzwingen. Letzteres ist hilfreich, da Bildlaufleisten nicht triviale Layoutverschiebungen verursachen können, da der Inhalt "above the fold" bei Änderungen der Breite neu fließt. Sollte jedoch hauptsächlich auf Plattformen mit Nicht-Overlay-Bildlaufleisten wie Windows auftreten. Aber: breaks position: sticky weil diese Elemente niemals aus dem Container scrollen.

    Wenn Sie es mit Kopfzeilen zu tun haben, die beim Scrollen fest oder klebrig oben auf der Seite positioniert werden, reservieren Sie Platz für die Kopfzeile, wenn sie verklemmt wird, z. B. mit einem Platzhalterelement oder einem margin-top auf dem Inhalt. Eine Ausnahme sollten Cookie-Consent-Banner sein, die keine Auswirkungen auf CLS haben sollten, aber manchmal tun sie es: es hängt von der Implementierung ab. In diesem Twitter-Thread finden Sie einige interessante Strategien und Erkenntnisse.

    Bei einer Registerkartenkomponente, die unterschiedlich viele Texte enthalten kann, können Sie Layoutverschiebungen mit CSS-Rasterstapeln verhindern. Indem wir den Inhalt jeder Registerkarte im selben Rasterbereich platzieren und jeweils einen davon ausblenden, können wir sicherstellen, dass der Container immer die Höhe des größeren Elements einnimmt, sodass keine Layoutverschiebungen auftreten.

    Ah, und natürlich kann unendliches Scrollen und "Mehr laden" auch zu Layoutverschiebungen führen, wenn sich Inhalte unterhalb der Liste befinden (z. B. Fußzeile). Um CLS zu verbessern, reservieren Sie genügend Platz für Inhalte, die geladen würden, bevor der Benutzer zu diesem Teil der Seite scrollt, entfernen Sie die Fußzeile oder alle DOM-Elemente am unteren Rand der Seite, die durch das Laden von Inhalten nach unten gedrückt werden könnten. Daten und Bilder für „Below-the-Fold“-Inhalte vorab abrufen, sodass sie bereits da sind, wenn ein Nutzer so weit scrollt. Sie können Listenvirtualisierungsbibliotheken wie das React-Window verwenden, um auch lange Listen zu optimieren ( Danke, Addy Osmani! ).

    Um sicherzustellen, dass die Auswirkungen von Umbrüchen eingedämmt werden, messen Sie die Layoutstabilität mit der Layout Instability API. Damit können Sie den Cumulative Layout Shift ( CLS ) Score berechnen und ihn als Anforderung in Ihre Tests aufnehmen, sodass Sie immer dann, wenn eine Regression auftritt, diese nachverfolgen und beheben können.

    Um den Layout-Shift-Score zu berechnen, betrachtet der Browser die Ansichtsfenstergröße und die Bewegung instabiler Elemente im Ansichtsfenster zwischen zwei gerenderten Frames. Im Idealfall wäre die Punktzahl nahe 0 . Es gibt einen großartigen Leitfaden von Milica Mihajlija und Philip Walton darüber, was CLS ist und wie man es misst. Dies ist ein guter Ausgangspunkt, um die wahrgenommene Leistung zu messen und aufrechtzuerhalten und Unterbrechungen zu vermeiden, insbesondere bei geschäftskritischen Aufgaben.

    Schneller Tipp : Um herauszufinden, was eine Layoutverschiebung in DevTools verursacht hat, können Sie Layoutverschiebungen unter „Erfahrung“ im Leistungsbereich untersuchen.

    Bonus : Wenn Sie Reflows und Repaints reduzieren möchten, sehen Sie sich Charis Theodoulou's guide to Minimizing DOM Reflow/Layout Thrashing und Paul Irish's list of What forces layout/reflow sowie CSSTriggers.com an, eine Referenztabelle zu CSS-Eigenschaften, die Layout, Paint auslösen und Compositing.

Inhaltsverzeichnis

  1. Vorbereitung: Planung und Metriken
  2. Realistische Ziele setzen
  3. Die Umgebung definieren
  4. Asset-Optimierungen
  5. Build-Optimierungen
  6. Lieferoptimierungen
  7. Netzwerk, HTTP/2, HTTP/3
  8. Testen und Überwachen
  9. Schnelle Gewinne
  10. Alles auf einer Seite
  11. Checkliste herunterladen (PDF, Apple Pages, MS Word)
  12. Abonnieren Sie unseren E-Mail-Newsletter, um die nächsten Anleitungen nicht zu verpassen.