Neuerungen bei der Angular NgOptimizedImage-Anweisung

Alex Castle
Alex Castle

Vor etwas mehr als einem Jahr hat das Chrome Aurora-Team die Richtlinie Angular NgOptimizedImage veröffentlicht. Mit der Richtlinie soll hauptsächlich die Leistung verbessert werden, gemessen an 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 standardmäßiges <img>-Element ist.

2023 haben wir die Richtlinie um neue Funktionen erweitert. In diesem Beitrag werden die wichtigsten dieser neuen Funktionen beschrieben. Dabei wird betont, warum wir die einzelnen Funktionen priorisieren und wie sie die Leistung von Angular-Anwendungen verbessern können.

Neue Funktionen

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

Ausfüllmodus

Das Festlegen der Größe deiner Bilder durch die Angabe eines width- und height-Attributs ist sehr wichtig, um Layoutverschiebungen zu reduzieren. Denn Browser müssen das Seitenverhältnis des Bildes kennen, um Platz dafür zu sparen. Die Größenanpassung von Bildern ist für Anwendungsentwickler jedoch zusätzliche Arbeit und ist bei einigen Anwendungsfällen für Bilder nicht sinnvoll.

Das ist die erste wichtige Funktion, die der Bildkomponente nach der Entwicklervorschau hinzugefügt wurde: der Füllmodus. So können Entwickler Bilder einschließen, ohne dass die Größe explizit geändert werden muss und ohne dass Layoutverschiebungen auftreten.

Im Füllmodus ist die Anforderung an die Bildgröße deaktiviert und das Bild wird automatisch so gestaltet, dass es das enthaltene Element füllt. Dabei wird das Seitenverhältnis eines Bildes von dem Platz entkoppelt, den es auf der Seite einnimmt, und Sie haben 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 den background-image-Stil hätte, und 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 steuern, 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 Verfahren zur Bildoptimierung ist die Verwendung des Attributs srcset. Damit wird sichergestellt, dass Bilder in der richtigen Größe für jedes Gerät heruntergeladen werden, über das auf Ihre App zugegriffen wird. Wenn du srcset in deiner App verwendest, kannst du Bandbreite vermeiden und deinen LCP Core Web Vitals-Wert erheblich verbessern.

Der Nachteil des Attributs srcset ist, dass die Implementierung mühsam sein kann. Beim manuellen Ausschreiben von srcset-Werten werden jedem Bildelement in Ihrer App mehrere Markup-Zeilen hinzugefügt, jeweils mit mehreren benutzerdefinierten URLs für jedes srcset. Außerdem müssen Sie sich für eine Reihe von Haltepunkten entscheiden, was kompliziert ist, da sie bei gängigen Geräten sowohl die Bildschirmdichten als auch die Größe des Darstellungsbereichs darstellen können.

Aus diesem Grund war die Einbindung der automatisierten srcset-Generierung in die NgOptimizedImage-Anweisung ein wichtiger Meilenstein nach der Einführung. Durch diese Ergänzung kann jede Anwendung, die ein CDN verwendet und die Bildgröße unterstützt, alle mit der NgOptimizedImage-Anweisung generierten "srcsets" vollständig, anpassbar und automatisch zu jedem Bild hinzufügen.

Wir haben eine vereinfachte API zum Festlegen der sizes-Eigenschaft hinzugefügt, mit der sichergestellt wird, dass jedes Bild den richtigen srcset-Typ erhält. Wenn Sie kein sizes-Attribut einfügen, wissen wir, dass das Bild eine feste Größe haben muss, und sollte ein dichteabhängiges srcset erhalten, zum Beispiel:

<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 stellt sicher, dass Bilder in einer Größe geliefert werden, die die Pixeldichte des Geräts des Nutzers berücksichtigt.

Wenn Sie jedoch das Attribut sizes angeben, generiert NgOptimizedImage mithilfe der folgenden Standardliste von Haltepunkten ein responsives srcset, das Haltepunkte für viele gängige Geräte- und Bildgrößen enthält:

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

Preconnect-Generierung

Es ist wichtig, dass Nutzer das LCP-Bild schneller herunterladen, um den LCP zu verbessern. Im vorherigen Abschnitt haben Sie erfahren, wie srcset Sie bei der Übertragung kleinerer Bilddateien unterstützen kann. Eine ebenso wichtige Optimierung besteht jedoch darin, die Übertragung so schnell wie möglich zu starten. Dazu können Sie z. B. link rel="preconnect"-Tags verwenden, um eine Verbindung zu Ihrer Bilddomain herzustellen.

NgOptimizedImage hat von Anfang an gewarnt, wenn Sie keine Vorverbindung zur Domain Ihres LCP-Bilds herstellen können. Diese Warnung ist jedoch nicht die ideale Lösung. Wir möchten das Problem lieber für Sie beheben. Genau das erreicht NgOptimizedImage jetzt mit der automatisierten Generierung der Vorverbindung.

Zur Unterstützung dieser Funktion verwenden wir eine statische Codeanalyse, um Image-Domains in NgOptimizedImage-Ladeprogrammen zu erkennen und automatisch Preconnect-Link-Tags für diese Domains zu generieren. Es gibt Fälle, in denen manuelle Vorverbindungslinks erforderlich sind. Für die meisten Nutzer bedeutet die automatische Vorverbindung jedoch einen Schritt weniger, der für eine gute Bildleistung erforderlich ist.

Erweiterte Unterstützung für benutzerdefinierte Loader

Ein Schlüsselelement von NgOptimizedImage ist die Loader-Architektur, mit der die Anweisung automatisch URLs generieren kann, die auf das CDN des Anwendungsbildes zugeschnitten sind. Für weit verbreitete CDNs ist eine Reihe integrierter Loader enthalten. Außerdem können Sie benutzerdefinierte Loader verwenden, um NgOptimizedImage in fast jede Bildhosting-Lösung zu integrieren.

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

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 einen komplexeren benutzerdefinierten Loader finden Sie in der Angular-Dokumentation.

Ausführlichere Hinweise zur Bildleistung

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

In Angular 17 erweitern wir den Umfang der Hinweise zur Bildleistung auf alle Angular-Apps. Wenn wir Bildmuster erkennen, von denen wir wissen, dass sie die Leistung beeinträchtigen, wie z. B. Lazy Loading des LCP-Bilds oder das Herunterladen einer Datei, die für die Seite zu groß ist, informieren wir Sie, auch wenn Sie NgOptimizedImage nicht verwenden.

Die Bildleistung ist für alle Apps wichtig und wir arbeiten weiterhin an Schutzmaßnahmen, um häufige Fehler in Angular-Apps zu vermeiden.

Aussichten

Wir arbeiten bereits intensiv an der Entwicklung der nächsten Funktionen für NgOptimizedImage. Die Bildleistung bleibt unser zentrales Anliegen. Wir möchten aber auch Funktionen hinzufügen, die die Entwicklererfahrung verbessern, um dafür zu sorgen, dass NgOptimizedImage eine attraktive Option zur Aufnahme von Bildern in Angular-Anwendungen bleibt.

Eine Funktion, die uns wichtig ist, sind Bildplatzhalter. Diese werden häufig verwendet, um das Laden von Bildern in Webanwendungen zu verbessern. Sie können jedoch die Leistung beeinträchtigen, wenn sie falsch implementiert wird. Wir hoffen, ein leistungsorientiertes Image-Platzhaltersystem in NgOptimizedImage zu integrieren. Weitere Ankündigungen finden Sie in unserem Blog.