Scripts: async, defer
In der schnelllebigen Welt der Webentwicklung ist die Effizienz des Seitenladens entscheidend. JavaScript, ein Grundpfeiler der clientseitigen Programmierung, muss
Wo Sie ein <script> platzieren und wie Sie es laden, hat einen direkten Einfluss darauf, wie schnell Ihre Seite nutzbar wird. Standardmäßig können Skripte den Browser mitten im Render-Vorgang blockieren; die Attribute async und defer ermöglichen es Ihnen, dem Browser mitzuteilen, JavaScript im Hintergrund herunterzuladen. Dieser Artikel erklärt, wie gewöhnliche blockierende Skripte sich verhalten, was async und defer ändern, warum Modul-Skripte automatisch zurückgestellt werden und wie Sie für jedes Skript die richtige Option wählen.
Wie ein einfaches Skript das Parsing blockiert
Ein <script> ohne async oder defer ist render-blockierend. Wenn der HTML-Parser auf das Tag trifft, hält er den Seitenaufbau an, lädt das Skript (sofern es ein src hat), führt es vollständig aus und setzt erst dann das Parsing des restlichen Dokuments fort:
<p>...content before script...</p>
<script src="big.js"></script> <!-- parsing pauses here until big.js downloads AND runs -->
<p>...content after script (the user can't see this yet)...</p>Daraus ergeben sich zwei Konsequenzen:
- Das Skript kann DOM-Elemente, die nach ihm erscheinen, nicht sehen, da sie noch nicht geparst wurden.
- Der Benutzer starrt auf eine halb aufgebaute Seite, während das Skript heruntergeladen wird. Bei einer langsamen Verbindung ist dies das klassische „leere Seite"-Problem.
Der historische Workaround bestand darin, Skripte ganz unten im <body> zu platzieren. async und defer bieten eine sauberere Lösung: Das Tag bleibt im <head>, blockiert aber nicht mehr.
Sowohl
asyncals auchdeferbetreffen nur externe Skripte — sie erfordern das Attributsrc. Bei inline<script>-Blöcken werden sie ignoriert.
Das async-Attribut verstehen
Was ist das async-Attribut?
Wenn Sie das Attribut async zu einem <script>-Tag hinzufügen, weist es den Browser an, das Skript im Hintergrund herunterzuladen, ohne das HTML-Parsing zu blockieren. Sobald der Download abgeschlossen ist, unterbricht der Browser das Parsing, führt das Skript aus und fährt dann fort. Da Download-Zeiten variieren, werden async-Skripte ausgeführt, sobald sie bereit sind — in unvorhersehbarer Reihenfolge, möglicherweise bevor der Rest des Dokuments geparst wurde.
Dadurch eignet sich async hervorragend für unabhängige Skripte, die weder auf den DOM noch aufeinander angewiesen sind: Analysetools, Werbung und andere „fire-and-forget"-Tracker.
Codebeispiel: async verwenden
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Async Example</title>
</head>
<body>
<h1>Testing Async</h1>
<script async src="https://example.com/async-script.js"></script>
</body>
</html>Vorteile und Kompromisse von async
- Nicht-blockierend: Das HTML-Parsing läuft weiter, während das Skript heruntergeladen wird.
- Wird so schnell wie möglich ausgeführt: Das Skript wird in dem Moment ausgeführt, in dem der Download abgeschlossen ist — gut für unabhängige Skripte.
- Keine garantierte Reihenfolge: Bei mehreren
async-Skripten wird dasjenige zuerst ausgeführt, das zuerst heruntergeladen wird. Verwenden Sieasyncniemals für Skripte, die voneinander abhängen. - Kann vor dem DOM ausgeführt werden: Es kann ausgeführt werden, bevor das Parsing abgeschlossen ist — gehen Sie daher nicht davon aus, dass spätere Elemente bereits existieren.
Das defer-Attribut nutzen
Was ist das defer-Attribut?
Das Attribut defer lädt das Skript ebenfalls im Hintergrund herunter, ohne das Parsing zu blockieren. Der Unterschied liegt im Zeitpunkt der Ausführung: Ein zurückgestelltes Skript wird erst nach dem vollständigen Parsen des HTML-Dokuments ausgeführt, und zwar unmittelbar bevor das Ereignis DOMContentLoaded ausgelöst wird. Zurückgestellte Skripte behalten außerdem ihre Dokumentreihenfolge — das erste defer-Tag wird stets vor dem zweiten ausgeführt, unabhängig davon, welches zuerst heruntergeladen wird.
Damit ist defer die richtige Standardwahl für Ihren Anwendungscode: Der gesamte DOM ist garantiert vorhanden, und abhängige Skripte bleiben in der richtigen Reihenfolge.
Codebeispiel: defer verwenden
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Defer Example</title>
</head>
<body>
<h1>Testing Defer</h1>
<script defer src="https://example.com/defer-script.js"></script>
</body>
</html>Vorteile der Verwendung von defer
- DOM bereit: Das gesamte HTML-Dokument wird geparst, bevor das Skript ausgeführt wird.
- Reihenfolge eingehalten: Skripte werden in Dokumentreihenfolge ausgeführt, was für Skripte, die voneinander abhängen, unerlässlich ist.
Modul-Skripte werden standardmäßig zurückgestellt
Ein <script type="module"> verhält sich automatisch wie ein zurückgestelltes Skript — Sie müssen defer nicht hinzufügen. Es wird geladen, ohne das Parsing zu blockieren, und wird nach dem Parsen des Dokuments in der richtigen Reihenfolge ausgeführt. Um ein Modul stattdessen so schnell wie möglich auszuführen (das async-Verhalten), fügen Sie async explizit hinzu:
<!-- Deferred automatically; runs after parsing, in order -->
<script type="module" src="app.js"></script>
<!-- Opt into async: runs as soon as it (and its imports) are ready -->
<script type="module" async src="tracker.js"></script>Wenn Sie neu bei Modulen sind, lesen Sie die Einführung in Module.
async vs. defer auf einen Blick
| Verhalten | async | defer |
|---|---|---|
| Blockiert das HTML-Parsing? | Nein | Nein |
| Wann wird es ausgeführt? | Sobald der Download abgeschlossen ist | Nach dem Parsing, vor DOMContentLoaded |
| Ausführungsreihenfolge | Was zuerst heruntergeladen wird | Dokumentreihenfolge, garantiert |
| DOM vollständig verfügbar? | Nicht garantiert | Ja |
| Geeignet für | Unabhängige Skripte (Analysetools, Werbung) | App-Code, abhängige Skripte |
Eine einfache Faustregel:
- Verwenden Sie
async, wenn das Skript eigenständig ist — es hängt weder von anderen Skripten noch vom DOM ab. - Verwenden Sie
defer, wenn das Skript den gesamten DOM benötigt oder wenn die Ausführungsreihenfolge wichtig ist.
Praktisches Beispiel: Entscheidungen beim Laden von Skripten
Stellen Sie sich vor, Sie laden eine Dienstprogrammbibliothek (wie Lodash) sowie Ihre eigene Datei, die davon abhängt. Da die Reihenfolge hier wichtig ist, ist defer die richtige Wahl — beide werden im Hintergrund heruntergeladen, werden aber nach dem Parsing sequenziell ausgeführt:
<script defer src="https://cdn.jsdelivr.net/npm/lodash/lodash.min.js"></script>
<script defer src="script.js"></script>Hier ist garantiert, dass lodash.min.js vor script.js ausgeführt wird, und beide warten, bis die Seite geparst wurde. Wenn Sie diese auf async umstellen würden, bestünde das Risiko, dass script.js zuerst ausgeführt wird und fehlschlägt, weil Lodash noch nicht geladen ist.
Informationen zum Laden von Nicht-Skript-Ressourcen (Bilder, Styles) und zur Reaktion auf deren Erfolg oder Fehler finden Sie unter Ressourcen laden: onload und onerror.
Fazit
Die effektive Verwendung der Attribute async und defer in Script-Tags ist für die moderne Webentwicklung entscheidend. Durch das richtige Verstehen und Anwenden dieser Attribute können Entwickler schnellere Seitenladezeiten und eine bessere Benutzererfahrung gewährleisten. Das asynchrone Laden von Skripten dreht sich um Performance-Optimierung und die Entwicklung effizienter, benutzerorientierter Webanwendungen.