Vor etwas mehr als einem Jahr hat das Chrome Aurora-Team die Angular-Direktive „NgOptimizedImage“ eingeführt. Die Richtlinie konzentriert sich hauptsächlich auf die Verbesserung der Leistung, gemessen anhand der Core Web Vitals-Messwerte. Häufig verwendete Bildoptimierungen und Best Practices werden in einer nutzerorientierten API gebündelt, die nicht viel komplizierter ist als ein Standard-<img>
-Element.
2023 haben wir die Richtlinie um neue Funktionen erweitert. In diesem Beitrag werden die wichtigsten dieser neuen Funktionen beschrieben. Dabei liegt der Schwerpunkt darauf, warum wir uns entschieden haben, die einzelnen Funktionen zu priorisieren und wie sie dazu beitragen können, die Leistung von Angular-Anwendungen zu verbessern.
Neue Funktionen
NgOptimizedImage wurde im Laufe der Zeit erheblich verbessert. Dazu gehören die folgenden neuen Funktionen.
Füllmodus
Die Größe Ihrer Bilder durch Angabe der Attribute width
und height
ist eine äußerst wichtige Optimierung, um Layoutverschiebungen zu reduzieren. Browser müssen das Seitenverhältnis des Bildes kennen, um Platz dafür zu schaffen. Die Größe von Bildern zu ändern, ist jedoch zusätzliche Arbeit für App-Entwickler und macht bei einigen Anwendungsfällen für Bilder keinen Sinn.
Diese Spannung wird durch die erste wichtige Funktion behoben, die der Bildkomponente nach der Entwicklervorschau hinzugefügt wurde: der Füllungsmodus. So können Entwickler Bilder einfügen, ohne sie explizit zu skalieren und ohne dass sich das Layout ändert.
Im Füllmodus ist die Anforderung für die Bildgröße deaktiviert und das Bild wird automatisch so gestaltet, dass es das enthaltende Element ausfüllt. Dadurch wird das Seitenverhältnis eines Bildes vom Platz getrennt, den es auf der Seite einnimmt. So haben Sie mehr Kontrolle darüber, wie Bilder in Ihr Seitenlayout passen.
Im Füllmodus wird NgOptimizedImage als leistungsstärkere Alternative zur CSS-Eigenschaft background-image
verwendet. Platzieren Sie ein Bild in <div>
oder einem anderen Element, das das background-image
-Styling haben würde, und aktivieren Sie dann den Füllmodus, wie im vorherigen Codebeispiel gezeigt. Mit den CSS-Eigenschaften object-fit
und object-position
auf der <div>
können Sie festlegen, wie das Bild im Hintergrund positioniert wird.
// Height and width are required
<img ngSrc="example.com" height="300" width="400">
// Unless you use fill mode!
<div style="width: 100vw; height: 50em; position: relative">
<img ngSrc="example.com" fill>
</div>
Srcset-Generierung
Eine der effektivsten Methoden zur Bildoptimierung ist die Verwendung des Attributs srcset
, um dafür zu sorgen, dass für jedes Gerät, das auf Ihre Anwendung zugreift, Bilder in der richtigen Größe heruntergeladen werden. Wenn Sie srcset
in Ihrer gesamten App verwenden, können Sie Bandbreitenverschwendung vermeiden und den LCP-Wert für Core Web Vitals erheblich verbessern.
Der Nachteil des srcset
-Attributs ist, dass es umständlich zu implementieren sein kann. Wenn Sie srcset
-Werte manuell eingeben, müssen Sie jedem Bildelement in Ihrer App mehrere Zeilen Markup mit mehreren benutzerdefinierten URLs für jeden srcset
hinzufügen. Außerdem müssen Sie eine Reihe von Wendepunkten festlegen. Das ist schwierig, da sie sowohl die Bildschirmdichten als auch die Darstellungsbereiche gängiger Geräte darstellen können.
Deshalb war die automatische srcset-Generierung in der NgOptimizedImage-Direktive ein wichtiger Meilenstein nach der Einführung. Mit dieser Ergänzung können jeder Anwendung, die ein CDN verwendet, das die Bildgrößenänderung unterstützt, automatisch vollständige, anpassbare SrcSets für jedes Bild hinzugefügt werden, das mit der Direktive „NgOptimizedImage“ generiert wird.
Wir haben eine vereinfachte API zum Festlegen des Attributs sizes
hinzugefügt, mit der sichergestellt wird, dass jedes Bild den richtigen srcset
-Typ erhält. Wenn Sie kein sizes
-Attribut angeben, wissen wir, dass das Bild eine feste Größe haben soll und ein dichteabhängiges „srcset“ erhalten sollte, z. B.:
<img src="www.example.com/image.png" srcset="www.example.com/image.png?w=400 1x, www.example.com/image.png?w=800 2x" >
Diese Art von srcset sorgt dafür, dass Bilder in einer Größe bereitgestellt werden, die die Pixeldichte des Geräts des Nutzers berücksichtigt.
Wenn Sie die sizes
-Eigenschaft hingegen einschließen, generiert NgOptimizedImage
ein responsives Srcset mit den folgenden Standardlisten von Unterbrechungen für viele gängige Geräte- und Bildgrößen:
[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]
Generierung von Preconnects
Um den LCP zu verbessern, ist es wichtig, die Zeit zu verkürzen, die Nutzer für das Herunterladen des LCP-Bildes benötigen. Im vorherigen Abschnitt haben Sie gesehen, wie srcset
bei der Übertragung kleinerer Bilddateien helfen kann. Eine ebenso wichtige Optimierung besteht darin, die Übertragung so schnell wie möglich zu starten. Eine Möglichkeit dazu ist die Verwendung von link rel="preconnect"
-Tags, um die Verbindung zu Ihrer Bilddomain zu starten.
NgOptimizedImage warnt schon immer, wenn Sie keine Vorabverbindung zur Domain Ihres LCP-Bildes herstellen. Eine Warnung ist jedoch nicht die ideale Lösung. Wir würden das Problem lieber direkt für Sie beheben. Und genau das macht NgOptimizedImage jetzt mit der automatischen Generierung von Preconnects.
Zur Unterstützung dieser Funktion versuchen wir, mithilfe der statischen Codeanalyse Bilddomains in NgOptimizedImage-Ladeprogrammen zu erkennen und automatisch Preconnect-Link-Tags für diese Domains zu generieren. Es kann immer noch Fälle geben, in denen manuelle Preconnect-Links erforderlich sind. Für die meisten Nutzer bedeutet die automatische Preconnect-Funktion jedoch einen Schritt weniger für eine gute Bildleistung.
Erweiterte Unterstützung für benutzerdefinierte Lader
Ein wichtiges Element von NgOptimizedImage ist die Ladearchitektur, mit der die Direktive automatisch URLs generieren kann, die auf das Bild-CDN der Anwendung zugeschnitten sind. Für gängige CDNs sind mehrere integrierte Loader enthalten. Außerdem können Sie benutzerdefinierte Lader verwenden, mit denen Sie NgOptimizedImage in fast jede Bild-Hosting-Lösung einbinden können.
Bei der Einführung waren diese benutzerdefinierten Lader nur eingeschränkt nutzbar und konnten nur das width
-Attribut aus dem Bildelement lesen. Aufgrund von Nutzerfeedback haben wir die Unterstützung für eine anpassbare loaderParams
-Datenstruktur hinzugefügt, mit der beliebige Daten vom Bildelement an den benutzerdefinierten Lader übergeben werden können. Mit der Erweiterung können benutzerdefinierte Lader so einfach oder komplex sein, wie es die Bildinfrastruktur einer Anwendung erfordert.
Das folgende Beispiel zeigt, wie ein einfacher benutzerdefinierter Loader mithilfe der loaderParams
API zwischen zwei alternativen Bilddomains auswählen kann:
const myCustomLoader = (config: ImageLoaderConfig) => {
if (config.loaderParams?.alternateDomain) {
return `https://alternate.domain.com/images/${config.src}`
}
return `https://primary.domain.com/images/${config.src}`;
};
Ein Beispiel für einen komplexeren benutzerdefinierten Lader finden Sie in der Angular-Dokumentation.
Erweiterte Hinweise zur Bildleistung
Bisher waren alle Benachrichtigungen zur Bildleistung, die wir Angular hinzugefügt haben, Teil der Direktive „NgOptimizedImage“. Wenn Sie die Richtlinie nicht in der App verwenden, erhalten Sie keine Informationen zu Problemen mit der Bildleistung.
In Angular 17 werden die Empfehlungen zur Bildleistung auf alle Angular-Apps ausgeweitet. Wenn wir Bildmuster erkennen, die wir als leistungsmindernd einstufen, z. B. das Lazy-Loading Ihres LCP-Bilds oder das Herunterladen einer Datei, die viel zu groß für die Seite ist, werden wir Sie benachrichtigen, auch wenn Sie NgOptimizedImage nicht verwenden.
Die Bildleistung ist für alle Apps wichtig. Wir werden daher auch weiterhin Schutzmaßnahmen entwickeln, um häufige Fehler in Angular-Apps zu vermeiden.
Aussichten
Wir arbeiten bereits an der nächsten Reihe von Funktionen für NgOptimizedImage. Die Bildleistung bleibt unser zentrales Anliegen. Wir möchten aber auch Funktionen hinzufügen, die die Entwicklerfreundlichkeit verbessern, damit NgOptimizedImage weiterhin eine attraktive Option für das Einfügen von Bildern in Angular-Anwendungen bleibt.
Eine Funktion, die für uns Priorität hat, sind Bildplatzhalter. Sie werden häufig verwendet, um das Laden von Bildern in Webanwendungen zu verbessern. Bei falscher Implementierung können sie jedoch die Leistung beeinträchtigen. Wir hoffen, in NgOptimizedImage ein leistungsorientiertes Bildplatzhaltersystem einbinden zu können. Weitere Ankündigungen folgen demnächst in unserem Blog.