Neuerungen bei der Angular NgOptimizedImage-Anweisung

Alex Schloss
Alex Castle

Vor etwas mehr als einem Jahr hat das Chrome Aurora-Team die Anweisung Angular NgOptimizedImage veröffentlicht. Der Schwerpunkt dieser Richtlinie liegt vor allem auf der Verbesserung der Leistung gemäß den Core Web Vitals-Messwerten. Sie bündelt gängige Bildoptimierungen und Best Practices in einer API für Nutzer, die nicht wesentlich komplizierter als ein Standard-<img>-Element ist.

2023 haben wir die Richtlinie um neue Funktionen ergänzt. In diesem Beitrag werden die wesentlichsten dieser neuen Funktionen beschrieben. Dabei wird hervorgehoben, warum wir uns für die einzelnen Funktionen entschieden haben und wie sie zur Leistungsverbesserung von Angular-Anwendungen beitragen können.

Neue Funktionen

NgOptimizedImage hat sich im Laufe der Zeit erheblich verbessert, einschließlich der folgenden neuen Funktionen.

Ausfüllmodus

Die Größenanpassung von Bildern über die Attribute width und height ist eine äußerst wichtige Optimierung zur Reduzierung von Layoutverschiebungen, da Browser das Seitenverhältnis des Bildes kennen müssen, um Platz zu sparen. Die Größenanpassung von Bildern ist für Anwendungsentwickler jedoch zusätzliche Arbeit und ist bei einigen Bildanwendungsfällen nicht sinnvoll.

Das erste wichtige Element, das der Vorschau nach der Entwicklung der Bildkomponente hinzugefügt wird, ist der Füllmodus. Auf diese Weise können Entwickler Bilder einbinden, ohne sie explizit in ihrer Größe anzupassen, und ohne Layoutverschiebungen.

Im Füllmodus wird die Anforderung zur Bildgröße deaktiviert. Das Bild wird automatisch so gestaltet, dass es das enthaltende Element ausfüllt. Dadurch wird das Seitenverhältnis des Bildes von dem Platz entkoppelt, den es auf der Seite einnimmt, und Sie können besser steuern, wie die Bilder in Ihr Seitenlayout passen.

Im Füllmodus wird NgOptimizedImage als leistungsstärkere Alternative zur CSS-Eigenschaft background-image verwendet. Platzieren Sie ein Bild innerhalb von <div> oder einem anderen Element, das den Stil background-image hätte. Aktivieren Sie dann den Füllmodus, wie im vorherigen Codebeispiel gezeigt. Mit den CSS-Eigenschaften object-fit und object-position für <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 Bildoptimierungstechniken ist die Verwendung des Attributs srcset, mit dem dafür gesorgt wird, dass Bilder in der richtigen Größe für jedes Gerät heruntergeladen werden, das auf Ihre App zugreift. Wenn Sie srcset in Ihrer gesamten App verwenden, können Sie verhindern, dass Bandbreite verschwendet wird, und Ihren LCP Core Web Vital erheblich verbessern.

Der Nachteil des Attributs srcset ist, dass die Implementierung umständlich sein kann. Wenn du srcset-Werte manuell ausgibst, musst du jedem Bildelement in deiner App mehrere Markup-Zeilen hinzufügen – komplett mit mehreren benutzerdefinierten URLs für jedes srcset-Element. Außerdem müssen Sie sich für eine Reihe von Haltepunkten entscheiden, was kompliziert ist, da diese sowohl die Bildschirmdichten als auch die Größe des Darstellungsbereichs gängiger Geräte darstellen können.

Aus diesem Grund war das Hinzufügen der automatisierten srcset-Generierung in die NgOptimizedImage-Anweisung ein wichtiger Meilenstein nach der Veröffentlichung. Durch diese Ergänzung kann jede Anwendung, die ein CDN verwendet, das die Bildgröße unterstützt, vollständige, anpassbare srcsets erhalten, die automatisch zu jedem Bild hinzugefügt werden, das mit der Anweisung NgOptimizedImage generiert wird.

Wir haben eine vereinfachte API zum Festlegen der sizes-Eigenschaft eingefü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 dichtebasiertes srcset wie das folgende erhalten sollte:

<img src="www.example.com/image.png" srcset="www.example.com/image.png?w=400 1x, www.example.com/image.png?w=800 2x" >

Mit dieser Art von srcset wird sichergestellt, dass Bilder in einer Größe bereitgestellt werden, die die Pixeldichte des Geräts des Nutzers berücksichtigt.

Wenn Sie dagegen das Attribut sizes verwenden, generiert NgOptimizedImage ein responsives srcset, das Haltepunkte für viele gängige Geräte- und Bildgrößen enthält. Dabei wird die folgende Standardliste von Haltepunkten verwendet:

[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]

Vorverbindungsgenerierung

Zur Verbesserung des LCP ist es wichtig, die Zeit zu reduzieren, die Nutzer zum Herunterladen des LCP-Bilds benötigen. Im vorherigen Abschnitt wurde gezeigt, wie srcset Sie bei der Übertragung kleinerer Bilddateien unterstützen kann. Eine ebenso wichtige Optimierung besteht darin, mit der Übertragung so schnell wie möglich zu beginnen. Eine Möglichkeit dafür ist das Verwenden von link rel="preconnect"-Tags, um die Verbindung zu Ihrer Image-Domain schnell herzustellen.

NgOptimizedImage hat von Anfang an eine Warnung ausgegeben, wenn Sie keine Vorverbindung zur Domain Ihres LCP-Images herstellen können. Allerdings stellt die Warnung keine ideale Lösung dar. Wir möchten das Problem einfach für Sie beheben. Genau das macht NgOptimizedImage jetzt mit der automatischen Generierung von Vorabverbindungen.

Zur Unterstützung dieser Funktion verwenden wir eine statische Codeanalyse, um Bilddomains in NgOptimizedImage-Ladeprogrammen zu erkennen und automatisch Preconnect-Link-Tags für diese Domains zu generieren. In manchen Fällen sind zwar manuelle Vorverbindungslinks erforderlich, aber bei den meisten Nutzern bedeutet die automatische Vorverbindung einen Schritt weniger, um eine gute Bildleistung zu erzielen.

Erweiterter Support für benutzerdefinierte Loader

Ein Schlüsselelement von NgOptimizedImage ist die Ladeprogramm-Architektur, mit der die Anweisung automatisch URLs generieren kann, die auf das Image-CDN der Anwendung zugeschnitten sind. Für gängige CDNs ist eine Reihe von integrierten Loadern enthalten. Darüber hinaus bieten wir die Verwendung von benutzerdefinierten Loadern an, mit denen Sie NgOptimizedImage in fast jede Bildhosting-Lösung einbinden können.

Zu Beginn waren diese benutzerdefinierten Loader vom Umfang beschränkt und konnten das Attribut width nur aus dem Bildelement lesen. Als Reaktion auf Nutzerfeedback haben wir die Unterstützung für eine anpassbare loaderParams-Datenstruktur hinzugefügt, mit der beliebige Daten vom Bildelement an das benutzerdefinierte Ladeprogramm übergeben werden können. Mit der Erweiterung können benutzerdefinierte Loader so einfach oder so komplex sein, wie es von der Image-Infrastruktur einer Anwendung gefordert wird.

Das folgende Beispiel zeigt, wie ein einfaches benutzerdefiniertes Ladeprogramm mit der loaderParams API zwischen zwei alternativen Bilddomains auswählen könnte:

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 ein komplexeres benutzerdefiniertes Ladeprogramm finden Sie in der Angular-Dokumentation.

Erweiterte Anleitungen zur Bildleistung

Bisher war jede Benachrichtigung zur Bildleistung, die wir Angular hinzugefügt haben, Teil der Anweisung „NgOptimizedImage“. Wenn Sie die Anweisung nicht in der App verwenden, erhalten Sie keine Hinweise zu Problemen mit der Bildleistung.

In Angular 17 weiten wir den Leitfaden zur Bildleistung auf alle Angular-Apps aus. Wenn wir Bildmuster erkennen, von denen wir wissen, dass sie die Leistung beeinträchtigen, wie etwa Lazy Loading Ihres LCP-Bildes oder Herunterladen einer Datei, die viel zu groß für die Seite ist, informieren wir Sie, auch wenn Sie NgOptimizedImage nicht verwenden.

Die Bildleistung ist für alle Apps wichtig und wir freuen uns darauf, weitere Schutzmaßnahmen zu entwickeln, mit denen häufige Fehler in Angular-Apps vermieden werden können.

Aussichten

Wir arbeiten bereits intensiv an der Entwicklung der nächsten Funktionen für NgOptimizedImage. Die Bildleistung ist nach wie vor unser Hauptanliegen, wir möchten aber auch Funktionen hinzufügen, die die Entwicklererfahrung verbessern, um sicherzustellen, dass NgOptimizedImage weiterhin eine attraktive Option für die Aufnahme von Bildern in Angular-Anwendungen ist.

Eine Funktion, die uns sehr am Herzen liegt, sind Bildplatzhalter. Sie werden häufig verwendet, um das Laden von Bildern in Webanwendungen zu verbessern, können aber bei falscher Implementierung die Leistung beeinträchtigen. Wir hoffen, in NgOptimizedImage ein Platzhaltersystem für Bilder zu implementieren, bei dem die Leistung im Vordergrund steht. Weitere Ankündigungen finden Sie in unserem Blog.