Lazy Loading von Bildern ist eine effektive Möglichkeit, die Leistung Ihrer Angular-Anwendungen zu verbessern, insbesondere bei großen Bildern oder Seiten mit vielen Medieninhalten. In diesem Blogbeitrag erfahren Sie, wie Sie eine Angular-Direktive erstellen, die Bilder mithilfe der IntersectionObserver-API lazy loaded.
Was ist Lazy Loading?
Lazy Loading ist eine Technik zur Leistungsoptimierung, bei der Ressourcen (wie Bilder) erst geladen werden, wenn sie im Viewport angezeigt werden sollen. Dies reduziert die anfängliche Ladezeit der Seite und spart Bandbreite, da Bilder nur bei Bedarf geladen werden.
Einführung in die IntersectionObserver-API
Die IntersectionObserver-API ist eine moderne Browser-Funktion, die es Entwicklern ermöglicht, asynchron zu erkennen, wann ein Element in den Viewport eintritt oder ihn verlässt. Im Gegensatz zu älteren Techniken wie Scroll-Events funktioniert IntersectionObserver unabhängig vom Haupt-Thread des JavaScript-Codes, was zu einer flüssigeren Interaktion und besseren Leistung führt.
Die API eignet sich für Aufgaben wie Lazy Loading, unendliches Scrollen oder die Implementierung von scrollbasierten Animationen, ohne dass ständig Scroll-Events überwacht werden müssen, was zu Leistungsproblemen führen kann. Mit IntersectionObserver verwaltet der Browser die Beobachtung von DOM-Elementen effizient, ohne den Haupt-Thread oder Benutzerinteraktionen zu blockieren.
Warum IntersectionObserver verwenden?
Es gibt mehrere Vorteile der IntersectionObserver-API im Vergleich zu traditionellen Methoden:
- Nicht-blockierendes Verhalten: Sie funktioniert asynchron und blockiert nicht den Haupt-Thread. Dies ist eine enorme Verbesserung gegenüber älteren Techniken wie Scroll-Event-Listenern, die das Rendering verlangsamen können, wenn viele Elemente überwacht werden.
- Reduzierter CPU-Aufwand: Anstatt die Scroll-Position manuell zu überwachen oder
setTimeout/setIntervalzu verwenden, kümmert sich der Browser nativ um die Überwachung der Elemente. Dies reduziert den Aufwand für teure Layout-Neuberechnungen. - Effizientes Ressourcenmanagement: Sie können mehrere Elemente gleichzeitig mit einem einzelnen Beobachter überwachen, anstatt manuell Event-Listener an jedes Bild anzuhängen.
- Bessere Benutzererfahrung: Lazy Loading reduziert die anfängliche Ladezeit der Seite, sodass Benutzer sichtbare Inhalte schneller laden können, ohne auf alle Mediendateien warten zu müssen.
Erstellung der Lazy Loading-Direktive
Erstellen wir nun eine Angular-Direktive, die Bilder mit der IntersectionObserver-API lazy loaded. Die Direktive wird überwachen, wann ein Bild in den Viewport gelangt, und es dann dynamisch laden. Hier ist die Implementierung:
import {
AfterViewInit,
Directive,
ElementRef,
inject,
Inject,
Input, OnDestroy,
PLATFORM_ID,
Renderer2
} from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
@Directive({
standalone: true,
selector: '[saiLazyImgLoad]'
})
export class ImgLazyLoadDirective implements AfterViewInit, OnDestroy {
readonly elementRef: ElementRef = inject(ElementRef);
readonly renderer2: Renderer2 = inject(Renderer2);
private obs!: IntersectionObserver;
@Input() imgSrc?: string;
@Input() backGroundImageClass?: string;
constructor(
@Inject(PLATFORM_ID) private platform: NonNullable
) {}
ngAfterViewInit(): void {
if (isPlatformBrowser(this.platform)) {
this.hasIntersectionObserver()
? this.observerIntersection()
: this.loadImage();
}
}
private hasIntersectionObserver() {
return window && 'IntersectionObserver' in window;
}
private observerIntersection(): void {
this.obs = new IntersectionObserver((entries) => {
entries.forEach(({ isIntersecting }) => {
if (isIntersecting) {
this.loadImage();
this.obs.disconnect();
}
});
}, { threshold: 0.1 });
this.obs.observe(this.elementRef.nativeElement);
}
private loadImage(): void {
if (this.backGroundImageClass) {
this.renderer2.addClass(this.elementRef.nativeElement, this.backGroundImageClass);
return;
}
this.elementRef.nativeElement.src = this.imgSrc;
}
ngOnDestroy(): void {
this.obs?.disconnect();
}
}
Wie es funktioniert
Die ImgLazyLoadDirective funktioniert folgendermaßen:
- Sie prüft zunächst, ob die Anwendung im Browser ausgeführt wird (da Lazy Loading serverseitig nicht funktioniert).
- Sie überprüft, ob der Browser die
IntersectionObserver-API unterstützt. Wenn ja, wird ein Beobachter eingerichtet, der überwacht, wann das Bild in den Viewport gelangt. - Wenn das Bild in den Viewport kommt, wird es (oder das Hintergrundbild) dynamisch geladen, und der Beobachter wird getrennt, um Ressourcen zu sparen.
- Falls der Browser
IntersectionObservernicht unterstützt, wird das Bild sofort geladen.
Vorteile von IntersectionObserver gegenüber anderen Methoden
In der Vergangenheit haben Entwickler Techniken wie das Abhören von Scroll-Events verwendet, um festzustellen, wann ein Bild geladen werden soll. Dieser Ansatz erforderte ständige Überprüfungen und Neuberechnungen beim Scrollen, was die Leistung beeinträchtigen konnte, insbesondere bei einer großen Anzahl von Bildern oder Elementen auf der Seite.
Die IntersectionObserver-API stellt eine erhebliche Verbesserung dar, da sie:
- Den Haupt-Thread nicht blockiert: Im Gegensatz zu Scroll-Events, die während des Scrollens Neuberechnungen erfordern, läuft
IntersectionObserverasynchron. Es überwacht effizient Änderungen der Sichtbarkeit von Elementen, ohne Benutzerinteraktionen oder die UI-Renderleistung zu beeinträchtigen. - Die Leistung optimiert: Browser verwalten die Sichtbarkeitsüberprüfung intern, sodass der Prozess hochoptimiert ist und mehrere Elemente mit minimalem Aufwand überwacht werden können.
- Native Unterstützung durch den Browser: Die API wird nativ in modernen Browsern unterstützt, wodurch die Notwendigkeit für komplexe Drittanbieter-Bibliotheken oder Polyfills für grundlegende Lazy Loading-Funktionen entfällt.
Verwendung der Direktive
Sie können die Direktive in Ihren Angular-Templates verwenden, indem Sie einfach das Attribut saiLazyImgLoad an ein Bild-Element anfügen und das imgSrc oder die Hintergrundbild-Klasse angeben.
Beispiel mit Bild-Element
<img [saiLazyImgLoad] [imgSrc]="imageUrl" alt="Lazy Loaded Image" />
Beispiel mit Hintergrundbild
<div [saiLazyImgLoad] [backGroundImageClass]="'lazy-loaded-bg'">
Inhalt hier
</div>
Fazit
Die Verwendung der IntersectionObserver-API zusammen mit Angular-Direktiven ermöglicht es Ihnen, das Laden von Bildern einfach zu optimieren, indem Ressourcen nur dann geladen werden, wenn sie für den Benutzer sichtbar sind. Dies verbessert nicht nur die Leistung Ihrer Angular-Anwendungen, sondern sorgt auch für eine bessere Benutzererfahrung, indem Ladezeiten verkürzt und Bandbreite gespart werden.
Viel Spaß beim Programmieren!
