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.
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:
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.Priorisierung wichtiger Images
Ressourcenhinweise hinzufügen (z.B.
preload
oderpreconnect
), 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 mitpriority
gekennzeichnet, wird ein Fehler ausgegeben und der Entwickler wird aufgefordert, dem LCP-Bild das Attributpriority
hinzuzufügen.Letztendlich sorgt diese Kombination aus Automatisierung und Konformität dafür, dass das LCP-Bild den Hinweis
preconnect
und den Attributwert „fetchpriority
“ vonhigh
hat und kein Lazy Loading ist.- Damit wird die fetchpriorität des Bildes auf
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.
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.
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
undheight
angeben.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- Sie haben aus Versehen oder
- Wenn Sie in Ihrem CSS eine Dimension nach Prozentsatz definiert haben, die andere jedoch nicht, benötigt
width: 100%
beispielsweiseheight: auto
, damit das Bild in beiden Dimensionen größer wird.
Ü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 Attributesrcset
undsizes
hindeutet.Bilddichte:Die Anweisung gibt einen Fehler aus, wenn Sie versuchen, ein Bild mit einer Pixeldichte von mehr als
3x
insrcset
einzufügen. Beschreibungen, die höher als2x
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:
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 einenpreload
-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 vonpreload
-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
- undfetchpriority
-Hinweisen dazu, das Bild anstelle vonpreload
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!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.
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 vonsrcset
. Die Attributesrcset
undsizes
müssen jedoch für jedes Bild manuell angegeben werden. Zukünftig könnte die Anweisung die Attributesrcset
undsizes
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 Attributewidth
undheight
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:- Unterstützung eines zusätzlichen Modus (ähnlich der Bildlayoutoption „
fill
“ in Next.js), bei dem keine explizite Breite/Höhe definiert werden muss. - 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.
- Unterstützung eines zusätzlichen Modus (ähnlich der Bildlayoutoption „
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.