Skip to content

Deferred Loading (<@defer>)

Das <@defer>-Compiler-Tag ermöglicht das deklarative Verzögern von Komponenten und DOM-Subbäumen in Avenx.js. Der Inhalt wird nicht sofort gerendert, sondern erst dann geladen, wenn der konfigurierte Trigger ausgelöst wird.

Dies kann dazu beitragen, die anfängliche Rendering- und JavaScript-Arbeitslast zu reduzieren, indem nicht benötigte Inhalte erst bei Bedarf verarbeitet werden.


Um einen Template-Bereich zu verzögern, umhülle ihn einfach mit dem <@defer>-Tag:

<@defer>
<HeavyChart data="{{ state.chartData }}" />
</@defer>

Wenn kein when-Attribut angegeben wird, verwendet <@defer> standardmäßig den idle-Trigger. Dabei wird requestIdleCallback verwendet, sofern diese Browser-API verfügbar ist. Andernfalls wird auf einen kurzen Timer zurückgegriffen.


Über das when-Attribut lässt sich festlegen, wann der verzögerte Inhalt geladen werden soll:

Trigger Syntax Beschreibung
idle (Standard) <@defer when="idle"> Lädt den Inhalt während der Browser-Leerlaufzeit.
visible <@defer when="visible"> Lädt den Inhalt, sobald der Defer-Container im Viewport sichtbar wird.
interaction <@defer when="interaction"> Lädt den Inhalt bei einer Benutzerinteraktion. Aktuell lösen click oder mouseenter das Laden aus.
timer(ms) <@defer when="timer(1000)"> Lädt den Inhalt nach der angegebenen Verzögerung in Millisekunden.
Ausdruck <@defer when="state.showDetails"> Wertet den angegebenen Ausdruck aus und lädt den Inhalt, wenn das Ergebnis wahr ist.

Der idle-Trigger lädt den verzögerten Inhalt, sobald der Browser Leerlaufzeit zur Verfügung hat.

<@defer when="idle">
<HeavyChart />
</@defer>

Avenx.js verwendet dafür requestIdleCallback, sofern diese Browser-API verfügbar ist. Andernfalls wird ein kurzer Timer als Fallback verwendet.

Der visible-Trigger lädt den Inhalt, sobald der Defer-Container im Viewport sichtbar wird.

<@defer when="visible">
<HeavyChart />
</@defer>

Avenx.js verwendet dafür IntersectionObserver. Sobald der Container sichtbar wird, wird der Observer beendet und der verzögerte Inhalt geladen.

Der interaction-Trigger lädt den Inhalt, sobald der Benutzer mit dem Defer-Container interagiert.

Aktuell lösen sowohl click als auch mouseenter das Laden des Inhalts aus. Die Trigger-Werte click und hover werden ebenfalls als Interaktions-Trigger unterstützt.

<@defer when="click">
<HeavyChart />
</@defer>
<@defer when="hover">
<HeavyChart />
</@defer>

Der timer-Trigger lädt den verzögerten Inhalt nach Ablauf einer angegebenen Verzögerung in Millisekunden.

<@defer when="timer(2000)">
<BannerAd />
</@defer>

In diesem Beispiel wird der Inhalt nach 2000 Millisekunden (2 Sekunden) geladen. Avenx.js unterstützt auch Zeitangaben im Format 1000ms.

Ein Ausdruck kann als Trigger verwendet werden, um den verzögerten Inhalt abhängig vom aktuellen Zustand zu laden.

<@defer when="state.isReady">
<HeavyComponent />
</@defer>

Der Ausdruck wird ausgewertet, wenn der Defer-Container verarbeitet wird. Wenn das Ergebnis wahr ist, wird der verzögerte Inhalt geladen. Wird der Container später erneut verarbeitet, wird der Ausdruck erneut ausgewertet.

Platzhalter & Ladezustände (<@placeholder> & <@loading>)

Section titled “Platzhalter & Ladezustände (<@placeholder> & <@loading>)”

Innerhalb von <@defer> können optionale Sub-Tags verwendet werden.

<@placeholder> definiert den Inhalt, der angezeigt wird, während auf den konfigurierten Trigger gewartet wird.

<@defer when="visible">
<@placeholder>
<div class="skeleton-loader">
Diagramm wird geladen, sobald es sichtbar ist...
</div>
</@placeholder>
<HeavyChart data="{{ state.chartData }}" />
</@defer>

<@loading> wird vom Compiler erkannt und als separates Lade-Template vorbereitet.

<@defer when="visible">
<@loading>
<div class="spinner">Profil wird geladen...</div>
</@loading>
<UserProfileDetails user="{{ state.user }}" />
</@defer>

Aktueller Status: In der aktuellen synchronen Laufzeit wird das <@loading>-Template noch nicht angezeigt. Sobald der Trigger ausgelöst wird, wird der verzögerte Inhalt direkt gerendert. Eine aktive Anzeige des Ladezustands kann mit zukünftiger asynchroner Ladeunterstützung ergänzt werden.


Das Kombinieren mehrerer Trigger wird derzeit noch nicht unterstützt.

Beispielsweise kann folgende Syntax aktuell nicht verwendet werden:

<@defer when="visible; interaction">
<HeavyComponent />
</@defer>

Aktuell kann für einen <@defer>-Block nur ein Trigger angegeben werden. Die Unterstützung für mehrere kombinierte Trigger ist für eine zukünftige Erweiterung vorgesehen.

Avenx.js registriert für aktive Trigger entsprechende Cleanup-Funktionen.

Je nach verwendetem Trigger werden beispielsweise:

  • Event-Listener für click und mouseenter entfernt.
  • Timer mit clearTimeout() abgebrochen.
  • Idle-Callbacks mit cancelIdleCallback() abgebrochen, sofern verfügbar.
  • IntersectionObserver-Instanzen mit disconnect() beendet.

Wenn der Trigger ausgelöst wird und der verzögerte Inhalt geladen wird, wird die zugehörige Trigger-Cleanup-Funktion ausgeführt.

Hinweis: Die vollständige Bereinigung beim Unmount eines übergeordneten Components ist derzeit noch nicht garantiert. Die DeferManager.destroy()-Methode ist momentan noch ein Platzhalter und wird beim Component-Teardown noch nicht aufgerufen. Eine vollständige Unmount-Bereinigung ist für eine zukünftige Erweiterung vorgesehen.


Die Verarbeitung von <@defer> erfolgt in zwei wesentlichen Schritten:

  1. Kompilier-Schritt: Der ComponentParser erkennt <@defer> und wandelt es in einen speziellen Defer-Container um. Abhängig vom verwendeten Inhalt können darin Templates für <@placeholder>, <@loading> und den eigentlichen verzögerten Inhalt gespeichert werden.

  2. Laufzeit-Schritt: Der DeferManager verarbeitet die Defer-Container und richtet den konfigurierten Trigger ein. Je nach Trigger verwendet er beispielsweise requestIdleCallback, IntersectionObserver, Event-Listener oder setTimeout.

Sobald der Trigger ausgelöst wird, rendert der DeferManager den verzögerten Inhalt und entfernt zuvor gerenderten Placeholder-Inhalt.