| [ Web Proxy ] |
| Viewing: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/import/defer | [Back] [Original] |
Get to know MDN better
Dieser Inhalt wurde automatisch aus dem Englischen bersetzt, und kann Fehler enthalten. Erfahre mehr ber dieses Experiment.
Experimentell: Dies ist eine experimentelle Technologie
berprfen Sie die Browser-Kompatibilittstabelle sorgfltig vor der Verwendung auf produktiven Webseiten.
Die import defer-Deklaration verhlt sich wie regulre import-Deklarationen, fhrt jedoch zu einem verzgerten Modul-Namespace-Objekt. Das Modul und seine Abhngigkeiten werden vorab abgerufen und gelinkt, ihre synchrone Auswertung wird jedoch verzgert, bis auf Eigenschaften des Namespace zugegriffen wird. Module, die top-level await verwenden, werden eager ausgewertet.
import defer * as name from "module-name";
nameName, der auf das verzgerte Modul-Namespace-Objekt verweist. Muss ein gltiger JavaScript-Identifier sein.
module-nameDas Modul, aus dem importiert werden soll. Wird auf dieselbe Weise behandelt wie module-name in regulren import-Deklarationen.
Import-Attribute werden ebenfalls untersttzt, indem nach dem Modulspezifizierer eine with-Klausel verwendet wird.
defer ist kein reserviertes Wort. Beispielsweise ist import defer from "./module.js" weiterhin ein regulrer Standardimport, dessen lokale Bindung defer heit.
Standardmig fhrt die import-Deklaration viele Aufgaben gleichzeitig aus: das Auflsen des Modulspezifizierers, das Abrufen des Modulquellcodes, das Parsen (wobei mglicherweise transitive Abhngigkeiten entdeckt werden), das Linken und die Auswertung. Diese Form der eager Auswertung ist nicht immer erwnscht: Sie kann zu einem langsameren Start fhren, die Umgebung fr ihre Auswertung ist mglicherweise noch nicht vollstndig vorbereitet, oder das Modul muss mglicherweise gar nicht ausgewertet werden.
Der Importphasen-Modifizierer ermglicht es, den Modulimportprozess in einer bestimmten Phase anzuhalten. Durch Hinzufgen von defer nach import wird der Quellcode gelinkt, bleibt jedoch unausgewertet, sofern er synchron ausgewertet werden kann (d.h. kein top-level await verwendet). Der Zugriff auf einen Export ber den verzgerten Namespace wertet das Modul und alle Abhngigkeiten, die zuvor ausgewertet werden mssen, synchron aus. Der Zugriff gibt den Wert des Exports zurck, nachdem die Auswertung abgeschlossen ist. Dadurch wird der Top-Level-Code des Moduls ausgefhrt, nicht nur der Code, der zum Initialisieren des angeforderten Exports bentigt wird. Transitive Abhngigkeiten, die mit eigenen import defer-Deklarationen importiert wurden, knnen weiterhin verzgert bleiben.
Indem sichergestellt wird, dass der angehaltene Teilgraph synchron ausgewertet werden kann, kann import defer mit nahezu keinen Codenderungen an den Stellen verwendet werden, die das Modul nutzen:
// Before:
import * as ts from "typescript";
// The full typescript module graph evaluates here
function compileFile(path) {
const program = ts.createProgram([path], {});
}
// After:
import defer * as ts from "typescript";
// No code is evaluated; potentially faster startup
function compileFile(path) {
// The typescript module graph evaluates when `ts.createProgram`
// is accessed, i.e., when `compileFile` is called.
// If `compileFile` is never called, then the module graph
// is never evaluated.
const program = ts.createProgram([path], {});
}
Warnung: Das Verzgern eines Imports verndert, wann seine Seiteneffekte auftreten. Verzgern Sie keine Module, deren Seiteneffekte erforderlich sind, bevor der Rest Ihres Codes ausgefhrt wird, beispielsweise Module, die Polyfills installieren.
Anders als import source wird ein verzgertes Modul weiterhin vorab gelinkt. Das vorzeitige Linken ermglicht dem Modullader, Abhngigkeiten aufzulsen und fehlende Abhngigkeiten oder ungltige Imports zu erkennen, bevor das Modul verwendet wird. Wenn das Modul ungelinkt bleibt, werden Abhngigkeiten, die Sie mglicherweise nicht bentigen, nicht geladen, und Sie knnen steuern, wie es instanziiert wird.
Anders als import() wird das verzgerte Modul weiterhin vorab abgerufen, geparst und gelinkt, wodurch unntiges Async Coloring vermieden wird (die gesamte Kette von Funktionsaufrufen wird gezwungen, asynchron zu werden). import defer bietet auerdem die meisten Vorteile einer statischen Deklaration, beispielsweise eine bessere statische Analyse.
Beachten Sie, dass nur die Syntax fr Namespace-Imports untersttzt wird. Sie knnen beispielsweise nicht import defer { property } from "./my-module.js" verwenden, da die Ausfhrung durch den Eigenschaftszugriff auf das Namespace-Objekt ausgelst wird.
Der Modifizierer wird auf einen Import angewendet, nicht auf das Modul selbst. Wenn ein anderer Teil der Anwendung dasselbe Modul ohne defer importiert, wird das Modul wie blich ausgewertet. Beide Formen teilen sich denselben Modulzustand, und der Code des Moduls wird hchstens einmal ausgefhrt. Das ndern der Importphase erzeugt kein separates Modul im Cache:
import defer * as ts from "typescript";
// No code is evaluated
import * as ts2 from "typescript";
// The full typescript module graph evaluates here
function compileFile(path) {
// Accessing `ts.createProgram` no longer evaluates the subgraph
// because it's already evaluated.
const program = ts.createProgram([path], {});
}
Im Gegensatz dazu knnen Import-Attribute die Modulidentitt beeinflussen. Beispielsweise fordern diese beiden Deklarationen in einem Host, der Textmodule untersttzt, unterschiedliche Modultypen an:
import * as mod from "./module.js";
import text from "./module.js" with { type: "text" };
Die beiden Imports gelten als Imports aus unterschiedlichen Modulen, die zufllig denselben String-Spezifizierer teilen (im Web werden sie mit unterschiedlichen HTTP-Headern angefordert). Die untersttzten Attribute und ihre Auswirkungen auf das Laden und die Modulidentitt werden durch den Host definiert.
Ein verzgertes Modul-Namespace-Objekt verhlt sich weitgehend wie ein regulres Modul-Namespace-Objekt: Es hat einen null-Prototyp, ist nicht erweiterbar und versiegelt und stellt schreibgeschtzte Live-Bindings fr die Exports des Moduls bereit. Seine String-Schlssel sind aufzhlbar und lexikografisch sortiert. Der Standardexport ist als Eigenschaft mit dem Namen default verfgbar.
Es gibt drei Unterschiede zu einem regulren Namespace:
[Symbol.toStringTag]-Eigenschaft ist "Deferred Module" statt "Module". Dies bleibt auch nach der Auswertung so.then bereit, auch nicht nach der Auswertung. Das Lesen von namespace.then gibt immer undefined zurck. Dadurch wird verhindert, dass die Promise-Auflsung den Namespace als Thenable behandelt und die Auswertung auslst. Um auf einen solchen Export zuzugreifen, verwenden Sie einen regulren Import oder fhren Sie ein Zwischenmodul ein, das then unter einem anderen Namen reexportiert.Die verzgerten und regulren Namespaces fr dasselbe Modul sind unterschiedliche Objekte, auch nach der Auswertung. Wiederholte verzgerte Imports desselben Moduls, ob statisch oder dynamisch, teilen dasselbe verzgerte Namespace-Objekt.
Um das Verhalten Auslsen der Modulauswertung beim Zugriff auf Schlssel zu implementieren, ist der verzgerte Modul-Namespace im Wesentlichen ein Proxy, der die folgenden Aktionen abfngt, um die Modulauswertung auszulsen:
defineProperty() fr jeden String-Schlssel auer then: beispielsweise Object.defineProperty(namespace, "value", {}).
Hinweis: Da das Modul-Namespace-Objekt nicht erweiterbar und versiegelt ist, knnen Sie keine Eigenschaftsbeschreibung, einschlielich ihres Werts, sinnvoll hinzufgen oder ndern. Dennoch wird die Auswertung ausgelst, selbst wenn die Operation fehlschlgt.
Der Proxy fngt set() nicht ab. Das Setzen von Eigenschaften wie namespace.value = 1; schlgt immer fehl.
deleteProperty() fr jeden String-Schlssel auer then: beispielsweise delete namespace.value.
Hinweis: Sie knnen keine Eigenschaft, die der Namespace besitzt, tatschlich lschen. Dennoch wird die Auswertung ausgelst, selbst wenn die Operation fehlschlgt.
get() und getOwnPropertyDescriptor() fr jeden String-Schlssel auer then: beispielsweise namespace.value, namespace["missing"], const { default: value } = namespace, Object.getOwnPropertyDescriptor(namespace, "value").
Hinweis: Das Destrukturieren eines Exports auf oberster Ebene hebt daher die Verzgerung dieses Moduls auf.
has() fr jeden String-Schlssel auer then: beispielsweise "value" in namespace, Object.hasOwn(namespace, "missing").
ownKeys(): beispielsweise Object.keys(namespace), Object.getOwnPropertySymbols(namespace), for (const key in namespace) {}. Selbst das Aufzhlen ausschlielich von Symbol-Schlsseln lst die Auswertung aus.
Das bloe Referenzieren des Namespace, Zuweisen an eine andere Variable, Vergleichen seiner Identitt oder bergeben an eine Funktion lst keine Auswertung aus. Ebenso wenig das Lesen von then oder einer Eigenschaft mit Symbol-Schlssel wie namespace[Symbol.toStringTag]. Der Aufruf von Object.getPrototypeOf() oder Object.isExtensible() lst ebenfalls keine Auswertung aus. Object.isSealed() und Object.isFrozen() zhlen jedoch Schlssel auf und lsen daher die Auswertung aus.
Das Lesen einer Namespace-Eigenschaft erfolgt synchron und kann daher nicht auf eine asynchrone Modulauswertung warten. Module, die top-level await enthalten, werden zusammen mit den Abhngigkeiten, die zu ihrer Auswertung erforderlich sind, eager ausgewertet. Dies schliet Module ein, die ber weitere verzgerte Imports erreicht werden. Das importierende Modul wartet auf diese asynchrone Auswertung, bevor sein eigener Body ausgefhrt wird.
Wenn das direkt importierte Modul top-level await enthlt, wird seine Auswertung nicht verzgert. Wenn nur einige seiner Abhngigkeiten top-level await enthalten, werden diese Abhngigkeiten eager ausgewertet, aber die synchronen Teile des Graphen, die fr ihre Auswertung nicht erforderlich sind, knnen verzgert bleiben. Siehe Verzgern eines Moduls mit einer asynchronen Abhngigkeit.
Fehler beim Laden, Parsen und Linken werden nicht verzgert. Beispielsweise verhindert ein fehlendes Modul, ein Syntaxfehler in einer Abhngigkeit oder ein nicht aufgelster benannter Import die Ausfhrung des importierenden Moduls, auch wenn nie auf den verzgerten Namespace zugegriffen wird. Fehler aus eager ausgewerteten asynchronen Abhngigkeiten verhindern ebenfalls die Ausfhrung des importierenden Moduls.
Whrend der verzgerten Auswertung geworfene Fehler werden von der Operation, die die Auswertung auslst, synchron geworfen. Sie knnen sie mit try...catch um diese Operation herum abfangen. Der Fehler wird zwischengespeichert: Nachfolgende Operationen, die die Auswertung auslsen, werfen denselben Fehler, anstatt den Code des Moduls erneut auszufhren. Dies gilt auch, wenn ein anderer Import zuvor dazu gefhrt hat, dass die Auswertung des Moduls fehlgeschlagen ist.
Eine Operation, die die Auswertung auslst, wirft einen TypeError, wenn das Modul oder seine Abhngigkeiten nicht fr eine synchrone Auswertung bereit sind. Dies kann bei zyklischen Imports passieren, wenn ein Zugriff ein Modul erfordern wrde, das noch ausgewertet wird. Eine import defer-Deklaration macht nicht jede zyklische Abhngigkeit whrend der Initialisierung sicher zugreifbar. Ein Bereitschaftsfehler selbst markiert das angeforderte Modul nicht als fehlgeschlagen ausgewertet: Ein spterer Zugriff kann erfolgreich sein, sobald seine Abhngigkeiten bereit sind.
Das folgende Modul initialisiert eine Lookup-Tabelle, wenn sein Top-Level-Code ausgefhrt wird:
// -- squares.js --
console.log("Initializing squares");
const squares = Array.from({ length: 10000 }, (_, index) => index ** 2);
export function getSquare(index) {
return squares[index];
}
Das importierende Modul kann eine synchrone Funktion bereitstellen, ohne die Tabelle zu initialisieren, bis sie bentigt wird:
// -- main.js --
import defer * as squares from "./squares.js";
console.log("Ready");
export function showSquare(index) {
console.log(squares.getSquare(index));
}
showSquare(3); // Logs "Initializing squares", then 9
showSquare(4); // Logs 16; initialization is not repeated
"Ready" wird vor "Initializing squares" protokolliert. Wenn showSquare() nie aufgerufen wird und kein anderer Import dazu fhrt, dass squares.js ausgewertet wird, wird die Lookup-Tabelle nie initialisiert.
In diesem Beispiel hngt report.js (das selbst synchron ist) sowohl von einem asynchronen Konfigurationsmodul als auch von einem synchronen Formatierungsmodul ab.
// -- config.js --
export const locale = await Promise.resolve("en-US");
console.log("Configuration ready");
// -- format.js --
console.log("Formatting module evaluated");
export function format(value, locale) {
return new Intl.NumberFormat(locale).format(value);
}
// -- report.js --
import { locale } from "./config.js";
import { format } from "./format.js";
console.log("Report module evaluated");
export function createReport(value) {
return format(value, locale);
}
// -- main.js --
import defer * as report from "./report.js";
console.log("Main module evaluated");
console.log(report.createReport(1000));
Die Ausgabe lautet:
Configuration ready Main module evaluated Formatting module evaluated Report module evaluated 1,000
config.js wird vor main.js ausgewertet, weil es top-level await enthlt. Weder format.js noch report.js mssen ausgefhrt werden, um config.js auszuwerten, daher wird ihre Auswertung verzgert, bis auf report.createReport zugegriffen wird.
// -- broken.js --
export const value = 1;
throw new Error("Initialization failed");
// -- main.js --
import defer * as broken from "./broken.js";
for (let attempt = 0; attempt < 2; attempt++) {
try {
console.log(broken.value);
} catch (error) {
console.log(error.message); // "Initialization failed" on both attempts
}
}
Auch wenn value initialisiert wurde, bevor die Ausnahme geworfen wurde, fhrt der Zugriff darauf ber den verzgerten Namespace zum Werfen des zwischengespeicherten Auswertungsfehlers.
Es gibt keine export defer-Syntax (weitere Informationen finden Sie unter export). Sie knnen einen verzgerten Namespace importieren und anschlieend seine Bindung exportieren, ohne die Auswertung auszulsen:
// -- features.js --
import defer * as report from "./report.js";
export { report };
// -- main.js --
import { report } from "./features.js";
// Accessing an export through report triggers its deferred evaluation.
console.log(report.createReport(1000));
| Spezifikation |
|---|
| Deferred Imports Evaluation # sec-imports |
importimport.defer()Der Bauplan fr ein besseres Internet.
Teile dieses Inhalts sind 19982026 von einzelnen mozilla.org-Mitwirkenden. Inhalte sind verfgbar unter einer Creative-Commons-Lizenz.
| Web Proxy Viewer | New URL | Original Page |