Im Mai 2022 haben die Teams von Aurora und Angular angekündigt, dass sie gemeinsam an einer Bildrichtlinie für Angular arbeiten werden. Die Anweisung wurde kürzlich für die Entwicklervorschau im Rahmen von Angular v14.2 veröffentlicht. In diesem Beitrag wird erläutert, wie die neue Image-Anweisung NgOptimizedImage
die Bildoptimierung in Angular unterstützt.
Hintergrund
Bilder sind ein wichtiger und entscheidender Faktor für die Nutzererfahrung im Web.99, 9% der Webseiten generieren Anfragen nach einem oder mehreren Bildern. Bilder sind mit einem Medianwert von 982 Kilobyte pro Seite auch am wichtigsten für die Seitengröße.
Aufgrund ihrer zunehmenden Anzahl und Größe können Bilder die Leistung von Webseiten beeinträchtigen und sich negativ auf die Core Web Vitals-Messwerte auswirken. Bei 79, 4% der Desktopseiten war ein Bild 2021 das Largest Contentful Paint (LCP)-Element. Das Streben nach optimierten Bildern ist für viele von uns ein fester Bestandteil.
Das Aurora-Team glaubt daran, die Leistungsfähigkeit von Frameworks zu nutzen, um integrierte Lösungen für häufige Entwicklerherausforderungen bereitzustellen. Der erste Vorsprung in die Bildoptimierung war die Next.js-Bildkomponente. Das Team betrachtete diese Komponente als Testplattform, um zu ermitteln, ob die Verbesserung der Bildoptimierung (DX) für Entwickler zu Leistungsgewinnen für mehr Apps mit Frameworks führen könnte.
Die ersten Ergebnisse des Next.js-Nutzers Leboncoin waren ermutigend. Nach der Verwendung von next/image
konnte Leboncoin den LCP deutlich verbessern (von 2,4 Sek.auf 1,7 Sek.). Die anschließende Einführung von next/image
in der Community hat dazu beigetragen, dass die Next.js-Ursprünge die LCP-Grenzwerte erreichen. Bald gab es Anfragen für ähnliche Funktionen in anderen Frameworks, darunter auch Angular.
Daher hat Aurora sich mit Angular und Nuxt zusammengetan, um einen Prototyp für Bildkomponenten für diese Frameworks zu erstellen. Letztes Jahr wurde die Nuxt-Bildkomponente veröffentlicht. Jetzt wurde die Angular-Image-Anweisung (NgOptimizedImage
) veröffentlicht, um die Standardeinstellungen für die Bildoptimierung auf Angular zu setzen.
Empfehlung
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 über HTTPArchive auf Mobilgeräten gecrawlt werden, und wird bei NPM beinahe 3 Millionen pro Woche heruntergeladen.
![LCP für Angular-Websites im letzten Jahr.](https://developer.chrome.com/static/blog/angular-image-directive/image/lcp-angular-websites-th-313c9b6e8afd2.png?authuser=6&hl=de)
In Bezug auf die Core Web Vitals-Werte muss der Prozentsatz der Angular-Ursprünge, die den „guten“ LCP-Grenzwert erreichen, noch verbessert werden. Im Juni 2022 hatten nur 18,74% der Angular-Websites einen guten LCP 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 schlechteren LCP auf Angular-Websites sein.
Die Angular-Image-Anweisung wurde entwickelt, um diese Zahlen zu verbessern.
MVP für die NgOptimizedImage-Anweisung
Die MVP der Angular-Image-Anweisung baut auf den Lehren aus den bisher von Aurora erstellten Bildkomponenten auf und passte gleichzeitig das Design an die clientseitige Rendering-Erfahrung von Angular an. Viele der Probleme bei der standardmäßigen Bildoptimierung wurden durch eines der folgenden Unternehmen behoben:
- Starke Standardeinstellungen bereitstellen
- Fehler oder Warnungen zur Sicherstellung der Einhaltung von Best Practices
Die Highlights des Designs sind folgende:
Intelligentes Lazy Loading
Bilder, die beim Seitenaufbau nicht sichtbar sind (z. B. „below the fold“-Bilder oder versteckte Karussellbilder), sollten idealerweise Lazy Loading sein. Durch Lazy Loading werden Browserressourcen für andere wichtige Texte, Medien oder Skripts freigegeben. 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.
Die Angular-Image-Anweisung Lazy lädt nicht kritische Bilder standardmäßig und lädt nur eifrig Bilder, die als
priority
gekennzeichnet sind. Dadurch wird sichergestellt, dass die meisten Bilder ein optimales Ladeverhalten aufweisen.Wichtige Bilder priorisieren
Ressourcenhinweise hinzufügen (z.B.
preload
oderpreconnect
), um das Laden kritischer Bilder zu priorisieren, ist eine empfohlene Best Practice. Die meisten Apps verwenden sie jedoch nicht. Laut Web Almanac von 2021 verwenden nur 12,7% der mobilen Seiten Hinweise zum Vorabladen und nur 22,1% der mobilen Seiten Hinweise zum Vorabladen.Die Image-Anweisung wirkt sich auf zwei Fronten aus, wenn Images als Priorität gekennzeichnet sind.
- Die fetchpriorität des Images wird auf
"high"
gesetzt, sodass der Browser weiß, dass er das Image mit einer hohen Priorität herunterladen soll. - Im Entwicklungsmodus bestätigt eine Laufzeitprüfung, dass ein
preconnect
-Ressourcenhinweis eingefügt wurde, der dem Ursprung des Bildes entspricht.
Im Entwicklungsmodus verwendet die Anweisung auch die PerformanceObserver API, um zu prüfen, ob das LCP-Bild wie erwartet als
priority
markiert wurde. Wenn es nicht alspriority
gekennzeichnet ist, wird ein Fehler ausgegeben, in dem der Entwickler angewiesen wird, dem LCP-Bild das Attributpriority
hinzuzufügen.Letztendlich sorgt diese Kombination aus Automatisierung und Konformität dafür, dass das LCP-Bild einen
preconnect
-Hinweis und einenfetchpriority
-Attributwert vonhigh
hat und kein Lazy Loading ist.- Die fetchpriorität des Images wird auf
Optimierte Konfiguration für gängige Bildtools
Angular-Anwendungen sollten Bild-CDNs verwenden, die häufig standardmäßig Optimierungsdienste bereitstellen.
Die Anweisung regt die Verwendung von CDN-Bild-CDNs an, indem sie eine besonders ansprechende Entwicklererfahrung (DX) zur Konfiguration in der App bietet. Sie unterstützt eine Lade-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 der Verwendung der folgenden Bild-Tags und reduziert die Auszeichnungskosten, die Entwickler für jedes Bild einfü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 beliebtesten CDNs für Bilder. Diese Ladeprogramme formatieren Bild-URLs automatisch, um sicherzustellen, dass 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 verfügt die Anweisung auch über integrierte Prüfungen, mit denen sichergestellt wird, dass die Entwickler die empfohlenen Best Practices bei der Auszeichnung von Bildern befolgt haben. Die Image-Anweisung führt die folgenden Prüfungen durch.
Bilder ohne Größe:Die Anweisung „image“ gibt einen Fehler aus, wenn für das Bild-Markup keine explizite Breite und Höhe definiert wurden. Ungroße Bilder können Layoutverschiebungen verursachen, die sich auf den CLS-Messwert (Cumulative Layout Shift) der Seite auswirken. Als Best Practice wird empfohlen, für Bilder die Attribute
width
undheight
anzugeben.Seitenverhältnis: Die Bildanweisung gibt einen Fehler aus, um Entwickler darüber zu informieren, ob das Seitenverhältnis des im HTML definierten
width
:height
-Formats nicht dem tatsächlichen Seitenverhältnis des gerenderten Bilds entspricht. Dies kann dazu führen, dass das Bild auf dem Bildschirm verzerrt wirkt. Das kann passieren, wenn- Sie haben versehentlich die falschen Abmessungen (Breite oder Höhe) definiert.
- Wenn Sie in Ihrem CSS eine Dimension prozentual definiert haben, die andere aber nicht (z. B. benötigt
width: 100%
height: auto
, damit das Bild in beiden Dimensionen wächst).
Bilder mit Übergröße:Wenn für das Bild kein
srcset
definiert ist und das eigentliche Bild deutlich größer als das gerenderte Bild ist, wird in der Anweisung eine Warnung mit dem Hinweis angezeigt, die Attributesrcset
undsizes
zu verwenden.Bilddichte:Die Anweisung gibt einen Fehler aus, wenn Sie versuchen, in
srcset
ein Bild mit einer Pixeldichte von mehr als3x
aufzunehmen. Beschreibungen, die höher als2x
sind, werden in der Regel nicht empfohlen, da sie die unbeabsichtigte Folge haben, dass Mobilgeräte mit hoher Auflösung gezwungen werden, riesige Bilder herunterzuladen. Darüber hinaus kann das menschliche Auge keinen Unterschied über 2-facher Wert erkennen.
Herausforderungen
Die größte Herausforderung bei der Entwicklung von NgOptimizedImage
war die Anpassung von Strategien zur Bildoptimierung an ein clientseitiges Framework. Die Standardeinstellung für das Rendering auf Next.js ist „Server Side Rendering (SSR)“ oder „Static Site Generation“ (SSG), während dies bei Angular das clientseitige Rendering (CSR) ist. Obwohl Angular eine SSR-Bibliothek – Angular/universal – unterstützt, verwenden die meisten Angular-Anwendungen (ca. 60%) CSR.
Die Image-Anweisung wurde vollständig für CSR erstellt, damit sie dem typischen Anwendungsfall in Angular-Anwendungen entspricht. Dies führte zu zusätzlichen Einschränkungen und das Team musste überdenken, wie spezifische Optimierungen für CSR-Anwendungen entwickelt werden sollten.
Folgende Herausforderungen sind aufgetreten:
Unterstützende Ressourcenhinweise
Wenn Sie wichtige Assets vorab laden, können sie vom Browser früher erkannt werden. Das Einfügen von Ressourcenhinweisen in Angular-Apps ist jedoch aus folgenden Gründen kompliziert:
Manuelles Hinzufügen: Es ist für Entwickler 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 die<head>
des Dokuments für jede Route gleich (zumindest zum Zeitpunkt der Bereitstellung). Das Hinzufügen einespreload
-Hinweises zum<head>
würde bedeuten, dass die Ressource für alle Routen vorab geladen wird, selbst wenn sie nicht benötigt wird. Daher wird das manuelle Hinzufügen vonpreload
-Hinweisen nicht empfohlen.Automatisches Hinzufügen während des Renderings:Die Verwendung des Frameworks zum Hinzufügen von Hinweisen zum Vorabladen im Dokumenttitel während des Renderings in einer CSR-App ist nicht hilfreich. Da das Rendern erfolgt, nachdem JavaScript heruntergeladen und ausgeführt wurde, wird
<head>
zu spät gerendert, um keinen Wert zu haben.In der ersten Version der Anweisung dient eine Kombination aus
preconnect
- undfetchpriority
-Hinweisen dazu, das Bild anstelle einespreload
zu priorisieren. Aurora arbeitet jedoch derzeit mit dem Angular CLI-Team zusammen, um das automatische Einfügen von Ressourcenhinweisen zum Zeitpunkt der Build-Erstellung 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 bereitgestellt werden. Aus diesem Grund wird die Verwendung von Bild-CDNs empfohlen, um Bilder zu komprimieren und on demand in moderne Formate wie WebP oder AVIF zu konvertieren.
Die -Anweisung erzwingt zwar nicht die Verwendung von CDN-Images für Bilder, wird jedoch dringend empfohlen, diese zusammen mit der -Anweisung zu verwenden, und ihre integrierten Loader stellen sicher, dass die richtigen Konfigurationsoptionen verwendet werden.
Auswirkungen
In der folgenden Demo wird demonstriert, wie sich die Angular-Image-Anweisung auf die Bildleistung auswirken kann. Es werden zwei Websites verglichen:
Website 1:Hier werden native <img>
-Elemente mit Bildern verwendet, die über das Imgix-CDN ausgeliefert werden (mit Standardkonfigurationsoptionen).
Website 2:Verwenden Sie die Anweisung „image“ für alle Bilder. Sie enthält auch die Optimierungen, die direkt durch Warnungen oder Fehler empfohlen werden, die von der Anweisung ausgegeben werden.
![Vergleich von Filmstreifen: Website 1 mit nativen Bild-Tags im Vergleich zu Website 2 mit der Angular-Image-Richtlinie.](https://developer.chrome.com/static/blog/angular-image-directive/image/filmstrip-comparison-web-c03e5b7f51387.png?authuser=6&hl=de)
Das Team arbeitete mit Partnern zusammen, um die Auswirkungen der Image-Richtlinie auf die Leistung realer Angular-Anwendungen zu validieren.
Einer dieser Partner war Land's End. Es wurde erwartet, dass die Website einen guten Testfall für Ergebnisse darstellt, die echte Anwendungen sehen könnten.
Vor und nach Anwendung der Bildrichtlinie wurden in der QA-Umgebung Lighthouse-Lab-Tests durchgeführt. Auf Computern sank der Medianwert von LCP von 12 s auf 3 s, was eine Verbesserung des LCP um 75% darstellt. Auf Mobilgeräten sank der Medianwert von LCP von 20,2 Sek. auf 12 Sek. (Steigerung um 40,6 %).
Roadmap für die Zukunft
Dies ist nur die erste Rate des Designs für die Angular-Bildanweisung. In zukünftigen Versionen sind viele weitere Funktionen geplant, darunter:
Bessere Unterstützung für responsive Bilder:
NgOptimizedImage
unterstützt derzeit die Verwendung vonsrcset
, aber die Attributesrcset
undsizes
müssen für jedes Bild manuell angegeben werden. In Zukunft könnte die Anweisung die Attributesrcset
undsizes
automatisch generieren.Automatisches Einfügen von Ressourcenhinweisen
Möglicherweise ist es möglich, Angular CLI einzubinden, um Vorverbindungs- und Vorablade-Tags für kritische LCP-Images zu generieren.
Unterstützung für Angular SSR
Die MVP-Version wurde unter Berücksichtigung der CSR-Einschränkungen von Angular entwickelt, es wird jedoch auch wichtig sein, Lösungen zur Bildoptimierung für Angular SSR (Angular/Universal) zu erforschen.
Verbesserte Benutzeroberfläche für Entwickler
NgOptimizedImage
erfordert, dass für jedes Bild die Attributewidth
undheight
angegeben werden. Es kann jedoch für manche Entwickler mühsam sein, diese für jedes Image anzugeben. Die Entwicklererfahrung könnte in der nächsten Iteration wie folgt verbessert werden:- Sie unterstützen einen zusätzlichen Modus (ähnlich der Bildlayoutoption „
fill
“ in Next.js), bei dem keine explizite Breite/Höhe definiert werden muss. - Durch Einbindung der Befehlszeile die Breite und Höhe für lokale Bilder automatisch festlegen, indem die tatsächlichen Abmessungen des Bildes bestimmt werden.
- Sie unterstützen einen zusätzlichen Modus (ähnlich der Bildlayoutoption „
Fazit
Die Angular-Image-Anweisung wird stufenweise für Entwickler verfügbar sein, beginnend mit der Entwicklervorschauversion in Version 14.2.0. Probieren Sie NgOptimizedImage
aus und geben Sie Feedback!
Ein besonderer Dank geht an Katie Hempenius und Alex Castle für ihren Beitrag.