Signatur
Beschreibung
import.defer() ist die dynamische Variante von import defer * as ns from "…". Wie bei import() wird das angegebene Modul samt Abhängigkeiten asynchron geladen und verknüpft. Der Unterschied: Das Promise wird mit einem deferred module namespace object erfüllt, also einem „aufgeschobenen“ Namensraum-Objekt. Der Code des Moduls läuft zu diesem Zeitpunkt noch nicht.
Erst wenn Sie zum ersten Mal auf einen Export zugreifen (z. B. ns.formatDate), wird das Modul synchron ausgeführt, genau an dieser Stelle im Code. Danach verhält sich das Objekt wie ein normaler Modul-Namensraum. So entfallen Netzwerk-Wartezeiten (geladen ist ja schon alles), und die teils teure Initialisierung eines Moduls (Top-Level-Code, große Tabellen, Polyfills) fällt nur an, wenn sie wirklich gebraucht wird.
Typische Einsatzfälle sind schwere, selten genutzte Funktionen wie Export-Dialoge, Diagramm-Bibliotheken oder Fehlerberichte. Sie sollen frühzeitig vorgeladen, aber nicht gleich beim Start ausgeführt werden. Das verbessert die Startzeit, ohne dass Aufrufer später await brauchen.
Einschränkung: Enthalten das Modul oder eine seiner Abhängigkeiten Top-Level-await, lässt sich dieser asynchrone Teil nicht synchron nachholen. Solche Module werden deshalb bereits vor dem Erfüllen des Promises ausgeführt. Aufgeschoben wird nur der synchrone Teil des Modulgraphen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $moduleName Pflicht | string | Modul-Bezeichner, wie bei import(): ein relativer oder absoluter Pfad, eine URL oder ein Bare Specifier, der über eine Import-Map bzw. die Node.js-Auflösung aufgelöst wird. |
|
| $options | object | undefined | Optionales Objekt wie bei import(), z. B. { with: { type: "json" } } für Import-Attribute. |
Rückgabewert
Beispiele
Grundprinzip: Ausführung erst beim Zugriff
// heavy.js
// console.log("heavy.js wird ausgeführt");
// export const answer = 42;
const ns = await import.defer("./heavy.js");
console.log("Modul geladen, aber noch nicht ausgeführt");
// Erster Zugriff löst die synchrone Ausführung aus
console.log(ns.answer);
Schwere Export-Funktion vorladen, bei Klick sofort nutzen
// Beim Start im Hintergrund laden, aber nicht ausführen
const exporterPromise = import.defer("./pdf-exporter.js");
document.querySelector("#export").addEventListener("click", async () => {
const exporter = await exporterPromise; // meist schon erfüllt
// Erst hier läuft die teure Initialisierung des Moduls
const blob = exporter.createPdf(document.body);
console.log("PDF erzeugt:", blob.size, "Bytes");
});
Laufzeitfehler treten beim Zugriff auf
// broken.js: throw new Error("Init fehlgeschlagen");
const ns = await import.defer("./broken.js"); // kein Fehler hier
try {
ns.something; // Ausführung startet und wirft
} catch (err) {
console.error("Fehler beim Auswerten:", err.message);
}
Mit Import-Attributen (JSON-Modul)
const config = await import.defer("./config.json", {
with: { type: "json" }
});
// Erst jetzt wird das JSON-Modul ausgewertet
console.log(config.default.apiUrl);
// Wichtig · Fallstricke
- Kompatibilität:
import.defer()ist ein TC39-Vorschlag in Stufe 3 und bisher in kaum einer Engine standardmäßig aktiv. Einzelne Engines bieten es teils hinter Flags an. TypeScript (ab 5.9) und Babel verstehen die Syntax, Bundler unterstützen sie unterschiedlich gut. Prüfen Sie Ihre Zielumgebung vor dem Einsatz im Produktivcode. - Top-Level-
await: Asynchrone Module im Graphen werden sofort ausgeführt, nicht aufgeschoben. Die Einsparung fällt dann kleiner aus. - Synchrone Ausführung beim Zugriff: Der erste Eigenschaftszugriff kann unerwartet teuer sein oder eine Ausnahme werfen, etwa in einem Event-Handler oder einer Render-Schleife. Setzen Sie den Zugriff bei Bedarf in
try/catch. - Laut Vorschlag löst der Zugriff auf
then(und auf Symbol-Schlüssel wieSymbol.toStringTag) die Ausführung nicht aus. Deshalb kann das Namensraum-Objekt ein Promise erfüllen, ohne vorzeitig ausgewertet zu werden. - Wurde dasselbe Modul schon anderswo normal importiert und ausgeführt, gibt es nichts mehr aufzuschieben. Modulinstanzen werden wie üblich geteilt.
- Laden und Parsen passieren trotzdem vorab. Netzwerk- oder Syntaxfehler lehnen deshalb schon das Promise ab.