Native Browser-APIs wie ResizeObserver, IntersectionObserver oder Drittanbieter-Bibliotheken, die Listener registrieren, kennen Angulars Komponenten-Lifecycle nicht. Verdrahtet eine Direktive einen solchen Observer im Konstruktor, ohne ihn je abzubauen, hält der Observer eine starke Referenz auf das Host-Element — das verhindert die Garbage Collection selbst nachdem die Komponente zerstört und aus dem DOM entfernt wurde. Das ist ein klassisches Detached-Node-Leck, das in langlebigen SPAs mit häufigem View-Wechsel, etwa virtualisierten Listen oder router-gesteuerten Dashboards, unbegrenzt wächst. DestroyRef.onDestroy() ist der moderne, injizierbare Ersatz für die Implementierung von OnDestroy und funktioniert entscheidend auch in Direktiven, Services und sogar einfachen Funktionen, die aus einem Injection-Kontext heraus aufgerufen werden — nicht nur in Komponenten.
import { Directive, ElementRef, inject, DestroyRef } from '@angular/core';@Directive({selector: '[resizeObserverFix]',standalone: true,})export class ResizeObserverFixDirective {private readonly el = inject(ElementRef<HTMLElement>);private readonly destroyRef = inject(DestroyRef);constructor() {// Third-party ResizeObserver has no Angular lifecycle awareness.const observer = new ResizeObserver((entries) => {for (const entry of entries) {this.el.nativeElement.dataset['width'] =String(entry.contentRect.width);}});observer.observe(this.el.nativeElement);// Without this, the observer keeps a strong reference to a// detached DOM node after the directive's host is destroyed.this.destroyRef.onDestroy(() => observer.disconnect());}}