Bilder mit der Anweisung für gewinkelte Bilder optimieren

Karin Schneider
Kara Erickson
Leena Sohoni
Leena Sohoni

Im Mai 2022 haben die Teams von Aurora und Angular bekannt gegeben, dass sie gemeinsam an einer Bildrichtlinie für Angular arbeiten werden. Die Anweisung wurde vor Kurzem als Teil von Angular v14.2 für die Entwicklervorschau freigegeben. In diesem Beitrag wird erläutert, wie die neue Bildanweisung NgOptimizedImage die Bildoptimierung in Angular unterstützt.

Hintergrund

Bilder sind ein wesentlicher Bestandteil der Nutzererfahrung im Web, denn 99,9% der Webseiten generieren Anfragen nach einem oder mehreren Bildern. Außerdem tragen Bilder am meisten zur Seitengröße bei – mit einem Medianwert von 982 Kilobyte pro Seite.

Aufgrund der zunehmenden Anzahl und Größe von Bildern können Bilder die Leistung von Webseiten beeinträchtigen und sich auf die Core Web Vitals-Messwerte auswirken. 2021 war ein Bild auf 79, 4% der Computerseiten das LCP-Element (Largest Contentful Paint). Das Streben nach optimierten Bildern ist daher für viele von uns ein ständiges Bemühen.

Das Aurora-Team glaubt, die Möglichkeiten von Frameworks zu nutzen, um integrierte Lösungen für häufige Entwicklerherausforderungen bereitzustellen. Der erste Schritt in die Bildoptimierung war die Next.js-Bildkomponente. Das Unternehmen betrachtete diese Komponente als Testgrundlage, um herauszufinden, ob eine Verbesserung des Entwicklererlebnisses (DX) bei der Bildoptimierung zu Leistungsgewinnen für mehr Apps mit Frameworks führen könnte.

Die ersten Ergebnisse des Next.js-Nutzers Leboncoin waren ermutigend. Leboncoin verzeichnete nach der Einführung von next/image eine deutliche Verbesserung des LCP-Werts (von 2,4 auf 1,7 Sek.). Die anschließende Einführung von next/image in der Community spielte eine wichtige Rolle bei der Zunahme der Next.js-Ursprünge, die die LCP-Grenzwerte erreichten. Bald gab es Anfragen für ähnliche Funktionen in anderen Frameworks, darunter Angular.

Daraufhin beschloss Aurora, mit Angular und Nuxt einen Prototyp von Bildkomponenten für diese Frameworks zu erstellen. Letztes Jahr wurde die Nuxt-Bildkomponente veröffentlicht. Jetzt wurde die Anweisung für Angular-Bild (NgOptimizedImage) veröffentlicht, um die Standardeinstellungen für die Bildoptimierung auf Angular zu bringen.

Opportunity

Angular ist eines der führenden JavaScript-Frameworks, die derzeit von Entwicklern verwendet werden. Es wird von mehr als 50.000 Ursprüngen verwendet, die von HTTPArchive auf Mobilgeräten gecrawlt werden, und wird bei NPM wöchentlich fast 3 Millionen Mal heruntergeladen.

LCP für Angular-Websites innerhalb des letzten Jahres.

Anhand der Core Web Vitals-Werte lässt sich feststellen, welcher Prozentsatz der Angular-Ursprünge den LCP-Grenzwert für „gut“ erfüllt. Nur 18,74% der Angular-Websites hatten im Juni 2022 einen guten LCP-Wert auf Mobilgeräten. Da Bilder für mehr als 70% der Webseiten auf Mobilgeräten und Computern das LCP-Element sind, können nicht optimierte LCP-Bilder eine der Hauptursachen für einen schlechten LCP-Wert auf Angular-Websites sein.

Die Anweisung für Angular-Bild wurde entwickelt, um diese Zahlen zu verbessern.

MVP für die NgOptimizedImage-Anweisung

Das MVP der Angular-Bildanweisung baut auf Erkenntnissen aus den Bildkomponenten auf, die Aurora bisher erstellt hat, während das Design an die clientseitige Rendering-Erfahrung von Angular angepasst wurde. Viele der standardmäßigen Bildoptimierungsprobleme wurden entweder durch folgende Maßnahmen behoben:

  • Starke Standardwerte bereitstellen.
  • Ausgabe von Fehlern oder Warnungen, um die Einhaltung von Best Practices sicherzustellen.

Die Highlights des Designs sind:

  1. Intelligentes Lazy Loading

    Idealerweise sollten Bilder, die beim Seitenaufbau nicht sichtbar sind, z. B. „below the fold“-Bilder oder ausgeblendete Karussellbilder, Lazy Loading sein. Beim Lazy Loading werden Browserressourcen freigegeben, damit andere wichtige Texte, Medien oder Skripts geladen werden können. Die meisten Bilder sind nicht kritisch und sollten Lazy Loading verwendet werden.2021 wurde jedoch nur für 7, 8% der Seiten natives Lazy Loading verwendet.

    Bei der Angular-Image-Anweisung werden nicht kritische Images standardmäßig geladen. Es werden nur Images geladen, die speziell als priority gekennzeichnet sind. Dadurch wird für die meisten Bilder ein optimales Ladeverhalten erreicht.

  2. Priorisierung wichtiger Images

    Ressourcenhinweise hinzufügen (z.B. preload oder preconnect), um das Laden wichtiger Bilder zu priorisieren, ist eine empfohlene Best Practice. Sie werden jedoch von den meisten Apps nicht verwendet. Laut dem Web Almanac von 2021 verwenden nur 12,7% der mobilen Seiten Preconnect-Hinweise und nur 22,1% der mobilen Seiten Vorabladehinweise.

    Die "image"-Anweisung wirkt sich auf zwei Fronten aus, wenn Bilder als Priorität markiert sind.

    • Damit wird die fetchpriorität des Bildes auf "high" gesetzt, sodass der Browser weiß, dass das Bild mit einer hohen Priorität heruntergeladen werden soll.
    • Im Entwicklungsmodus bestätigt eine Laufzeitprüfung, dass ein preconnect-Ressourcenhinweis zum Ursprung des Bildes eingefügt wurde.

    Im Entwicklungsmodus wird von der Anweisung auch die PerformanceObserver API verwendet, um zu prüfen, ob das LCP-Image wie erwartet als priority markiert wurde. Ist sie nicht mit priority gekennzeichnet, wird ein Fehler ausgegeben und der Entwickler wird aufgefordert, dem LCP-Bild das Attribut priority hinzuzufügen.

    Letztendlich sorgt diese Kombination aus Automatisierung und Konformität dafür, dass das LCP-Bild den Hinweis preconnect und den Attributwert „fetchpriority“ von high hat und kein Lazy Loading ist.

  3. Optimierte Konfiguration für gängige Bildtools

    Es wird empfohlen, für Angular-Anwendungen Bild-CDNs zu verwenden, die häufig standardmäßig Optimierungsdienste bereitstellen.

    Die Anweisung ermutigt die Verwendung von Image-CDNs, indem sie ein besonders ansprechendes Entwicklererlebnis (DX) für deren Konfiguration in der App bietet. Sie unterstützt eine Ladeprogramm-API, mit der Sie den CDN-Anbieter und Ihre Basis-URL in Ihrer Konfiguration definieren können. Nach der Konfiguration musst du nur noch den Asset-Namen im Markup definieren. Beispiel:

    // in module providers:
    provideImgixLoader('https://mysite.net/assets/')
    
    // in markup
    <img ngSrc="image.png" >
    <img ngSrc="image2.png" >
    

    Dies entspricht dem Einschließen der folgenden Bild-Tags und verringert den Aufwand, den Entwickler für jedes Bild hinzufügen müssen.

    <img src="https://mysite.net/assets/image.png">
    <img src="https://mysite.net/assets/image2.png">
    

    Die Image-Anweisung bietet integrierte Loader mit optimaler Konfiguration für die gängigsten Image-CDNs. Mit diesen Loadern werden Bild-URLs automatisch formatiert, damit für jedes CDN das empfohlene Bildformat und die empfohlenen Komprimierungseinstellungen verwendet werden.

  4. Integrierte Fehler und Warnungen

    Zusätzlich zu den oben genannten integrierten Optimierungen enthält die Anweisung auch integrierte Prüfungen, um sicherzustellen, dass die Entwickler die empfohlenen Best Practices für das Bild-Markup befolgt haben. Die Image-Anweisung führt die folgenden Prüfungen durch.

    1. Bilder ohne Größenangabe:Die Bildanweisung gibt einen Fehler aus, wenn im Bild-Markup keine explizite Breite und Höhe definiert wurde. Bilder ohne Größe können zu Layoutverschiebungen führen, was sich auf den Messwert „Cumulative Layout Shift“ (CLS) einer Seite auswirkt. Um dies zu verhindern, sollten Sie für Bilder die Attribute width und height angeben.

    2. Seitenverhältnis:Die Bildanweisung gibt einen Fehler aus, um Entwickler zu informieren, wenn das Seitenverhältnis von width:height, das im HTML-Code definiert ist, nicht dem tatsächlichen Seitenverhältnis des gerenderten Bilds entspricht. Das kann dazu führen, dass das Bild auf dem Bildschirm verzerrt aussieht. Das kann passieren, wenn

      1. Sie haben aus Versehen oder
      2. Wenn Sie in Ihrem CSS eine Dimension nach Prozentsatz definiert haben, die andere jedoch nicht, benötigt width: 100% beispielsweise height: auto, damit das Bild in beiden Dimensionen größer wird.
    3. Übergroße Bilder: Wenn für das Bild kein srcset definiert ist und das intrinsische Bild deutlich größer als das gerenderte Bild ist, wird in der Anweisung eine Warnung angezeigt, die auf die Verwendung der Attribute srcset und sizes hindeutet.

    4. Bilddichte:Die Anweisung gibt einen Fehler aus, wenn Sie versuchen, ein Bild mit einer Pixeldichte von mehr als 3x in srcset einzufügen. Beschreibungen, die höher als 2x sind, werden generell nicht empfohlen, da sie unbeabsichtigte Folgen haben, weil Mobilgeräte mit hoher Auflösung z. B. große Bilder herunterladen müssen. Darüber hinaus kann das menschliche Auge über den doppelten Wert kaum einen großen Unterschied erkennen.

Challenges

Eine der größten Herausforderungen bei der Entwicklung von NgOptimizedImage war die Anpassung von Strategien zur Bildoptimierung an ein clientseitiges Framework. Standardmäßig wird unter Next.js das serverseitige Rendering (SSR) oder statische Websitegenerierung (SSG) verwendet, bei Angular dagegen das clientseitige Rendering (CSR). Angular unterstützt zwar eine SSR-Bibliothek (angular/universal), aber die meisten Angular-Apps (ca. 60%) verwenden CSR.

Die Image-Anweisung wurde vollständig für CSR erstellt und entspricht dem typischen Anwendungsfall in Angular-Apps. Dies setzte zusätzliche Einschränkungen und das Team musste überdenken, wie spezifische Optimierungen für CSR-Anwendungen vorgenommen werden können.

Im Folgenden finden Sie einige der Herausforderungen:

  1. Hilfreiche Ressourcenhinweise

    Wenn Sie wichtige Assets vorab laden, kann der Browser sie früher erkennen. Das Einfügen von Ressourcenhinweisen in Angular-Apps ist jedoch aus folgenden Gründen kompliziert:

    Manuelles Hinzufügen: Für Entwickler ist es schwierig, den Ressourcenhinweis preload manuell hinzuzufügen. Angular verwendet eine freigegebene Datei "index.html" für das gesamte Projekt oder für alle Routen auf der Website. Daher ist der <head> des Dokuments für jede Route gleich (zumindest bei der Bereitstellungszeit). Wenn du einen preload-Hinweis zu <head> hinzufügst, wird die Ressource für alle Routen vorab geladen, selbst wenn sie nicht benötigt werden. Daher wird das manuelle Hinzufügen von preload-Hinweisen nicht empfohlen.

    Automatisches Hinzufügen während des Renderings:Es hilft nicht, mithilfe des Frameworks während des Renderings in einer CSR-App Preload-Hinweise in die Kopfzeile des Dokuments einzufügen. Da das Rendering nach dem Herunterladen und Ausführen von JavaScript erfolgt, wird das <head>-Objekt zu spät gerendert, sodass es keinen Wert mehr enthält.

    In der ersten Version der Anweisung dient eine Kombination aus preconnect- und fetchpriority-Hinweisen dazu, das Bild anstelle von preload zu priorisieren. Aurora arbeitet jedoch derzeit mit dem Angular CLI-Team zusammen, um das automatische Einfügen von Ressourcenhinweisen zum Build-Zeitpunkt zu ermöglichen. Bleiben Sie dran!

  2. Bildgröße und -format auf dem Server optimieren

    Da Angular-Apps in der Regel clientseitig gerendert werden, können Bilder im Dateisystem nicht zum Zeitpunkt der Anfrage komprimiert und so bereitgestellt werden, wie sie sind. Aus diesem Grund wird die Verwendung von Bild-CDNs empfohlen, um Bilder zu komprimieren und sie bei Bedarf in moderne Formate wie WebP oder AVIF umzuwandeln.

    Die Anweisung erzwingt die Verwendung von CDNs für Bilder zwar nicht, es wird jedoch dringend empfohlen, sie zusammen mit der Anweisung zu verwenden, und ihre integrierten Loader stellen sicher, dass die richtigen Konfigurationsoptionen verwendet werden.

Auswirkungen

Die folgende Demo zeigt den Unterschied, den die Angular-Image-Anweisung auf die Image-Leistung haben kann. Es werden zwei Websites verglichen:

Website 1:Verwendet native <img>-Elemente mit Bildern, die über das Imgix-CDN bereitgestellt werden (mit Standardkonfigurationsoptionen).

Website 2:Verwenden Sie die Bildanweisung für alle Bilder. Sie enthält auch die Optimierungen, die direkt von Warnungen oder Fehlern empfohlen werden, die von der Anweisung ausgegeben werden.

Filmstreifen-Vergleich: Website 1 mit nativen Bild-Tags und Website 2 mit Angular-Bild-Richtlinie

Das Team arbeitete mit Partnern zusammen, um die Auswirkungen der Bildrichtlinie auf die Leistung echter Angular-Anwendungen in Unternehmen zu validieren.

Einer dieser Partner war Land's End. Es wurde erwartet, dass ihre Website ein guter Testlauf für Ergebnisse sein würde, die echte Anwendungen zeigen könnten.

Lighthouse Lab-Tests wurden in der QA-Umgebung vor und nach Verwendung der Image-Anweisung durchgeführt. Auf Computern sank der Medianwert für den LCP-Wert von 12 Sekunden auf 3 Sek., was einer Verbesserung des LCP um 75% entspricht. Auf Mobilgeräten sank der Medianwert für den LCP von 20,2 Sekunden auf 12 Sekunden (Verbesserung um 40,6 %).

Roadmap für die Zukunft

Dies ist nur der erste Teil des Designs für die Angular-Image-Anweisung. Für zukünftige Versionen sind viele weitere Funktionen geplant, darunter:

  • Bessere Unterstützung responsiver Bilder:

    NgOptimizedImage unterstützt derzeit die Verwendung von srcset. Die Attribute srcset und sizes müssen jedoch für jedes Bild manuell angegeben werden. Zukünftig könnte die Anweisung die Attribute srcset und sizes automatisch generieren.

  • Automatisches Einfügen von Ressourcenhinweisen

    Möglicherweise ist es möglich, die Angular CLI einzubinden, um Vorverbindungs- und Vorlade-Tags für wichtige LCP-Bilder zu generieren.

  • Unterstützung für Angular SSR

    Bei der Entwicklung der MVP-Version werden die Beschränkungen von Angular CSR berücksichtigt. Es ist jedoch auch wichtig, Lösungen zur Bildoptimierung für Angular SSR (winkel/universal) zu untersuchen.

  • Verbesserungen für Entwickler

    NgOptimizedImage setzt voraus, dass die Attribute width und height für jedes Bild angegeben werden. Allerdings kann es für einige Entwickler mühsam sein, diese für jedes Image anzugeben. Hier besteht das Potenzial, die Entwicklung in der nächsten Iteration wie folgt zu verbessern:

    1. Unterstützung eines zusätzlichen Modus (ähnlich der Bildlayoutoption „fill“ in Next.js), bei dem keine explizite Breite/Höhe definiert werden muss.
    2. Mit der CLI-Integration können Breite und Höhe für lokale Bilder automatisch festgelegt werden, indem die tatsächlichen Abmessungen des Bildes ermittelt werden.

Fazit

Die Anweisung für Angular-Images steht Entwicklern schrittweise zur Verfügung, beginnend mit der Entwicklervorschauversion in Version 14.2.0. Probieren Sie NgOptimizedImage aus und geben Sie uns Feedback.

Unser besonderer Dank gilt Katie Hempenius und Alex Castle für ihren Beitrag.