826 Stimmen

Script Tag - async & defer Skript-Tag - async & defer

Ich habe ein paar Fragen zu den Attributen async & defer für das </code> tag, die meines Wissens nur in HTML5-Browsern funktionieren.</p> <p>Eine meiner Websites hat zwei externe JavaScript-Dateien, die sich derzeit direkt über dem <code></body></code>-Tag befinden; die erste stammt von Google und die zweite ist ein lokales externes Skript.</p> <h2>Zur Seitenladegeschwindigkeit</h2> <ol> <li><p>Gibt es einen Vorteil darin, <code>async</code> zu den beiden Skripten hinzuzufügen, die sich am Ende der Seite befinden?</p> </li> <li><p>Gäbe es einen Vorteil darin, die Option <code>async</code> zu den beiden Skripten hinzuzufügen und sie oben auf der Seite im <code><head></code> zu platzieren?</p> </li> <li><p>Würde das bedeuten, dass sie während des Seitenladens heruntergeladen werden?</p> </li> <li><p>Ich gehe davon aus, dass dies Verzögerungen für HTML4-Browser verursachen würde, aber würde es die Seitenladung für HTML5-Browser beschleunigen?</p> </li> </ol> <h2>Verwendung von <code><script defer src=...</code></h2> <ol> <li>Würde das Laden der beiden Skripte im <code><head></code> mit dem Attribut <code>defer</code> den gleichen Effekt haben wie das Platzieren der Skripte vor dem <code></body></code>?</li> <li>Auch hier gehe ich davon aus, dass dies die HTML4-Browser verlangsamen würde.</li> </ol> <h2>Verwendung von <code><script async src=...</code></h2> <p>Wenn ich zwei Skripte mit <code>async</code> aktiviert habe</p> <ol> <li>Würden sie gleichzeitig heruntergeladen werden?</li> <li>Oder eines nach dem anderen mit dem Rest der Seite?</li> <li>Wird dann die Reihenfolge der Skripte zu einem Problem? Beispielsweise hängt ein Skript vom anderen ab, also wenn eines schneller heruntergeladen wird, könnte das zweite möglicherweise nicht korrekt ausgeführt werden usw.</li> </ol> <p>Sollte ich vielleicht besser alles so lassen, bis HTML5 häufiger verwendet wird?</p></x-turndown>

8 Stimmen

async ist neu(ish), aber defer ist seit IE4 Teil des IE. Defer wurde erst kürzlich für andere Browser hinzugefügt, aber ältere Versionen dieser Browser bleiben oft viel weniger erhalten.

5 Stimmen

Jetzt ist HTML5 sehr beliebt!

6 Stimmen

defer entspricht dem Platzieren von Skripten am Ende des HTML-Dokuments, was seit vielen Jahren üblich ist.

30voto

NavyaKumar Punkte 569

async und defer laden die Datei während des HTML-Parsens herunter. Beide unterbrechen nicht den Parser.

  • Das Skript mit dem Attribut async wird ausgeführt, sobald es heruntergeladen wurde. Das Skript mit dem Attribut defer wird nach Abschluss des DOM-Parsings ausgeführt.

  • Die Skripte, die mit async geladen werden, garantieren keine Reihenfolge. Die Skripte, die mit dem Attribut defer geladen werden, bewahren die Reihenfolge, in der sie im DOM erscheinen.

Verwenden Sie </code>, wenn das Skript von nichts abhängt, verwenden Sie <code><script defer></code>, wenn das Skript abhängig ist.</p> <p>Die beste Lösung wäre, das <code><script></code> am Ende des Body hinzuzufügen. Es wird keine Probleme mit Blockieren oder Rendern geben.</p></x-turndown>

1 Stimmen

Möchte hier nur eine Klarstellung machen, hier passieren zwei Dinge 1. Herunterladen von Ressourcen 2. Ausführung von Ressourcen. Das Herunterladen von Ressourcen in beiden Fällen (async und defer) blockiert nicht, das bedeutet, sie blockieren nicht das Parsen von HTML, während die Ausführung im async-Modus das Parsen blockiert und im Falle von defer die Ausführung nach dem Parsen des HTML-Markups erfolgt, daher nicht blockierend in diesem Fall.

0 Stimmen

@pOoOf Da die Anforderung und der Download von Ressourcen durch den HTTP-Anforderungsthread erfolgen, der parallel zum GUI-Render-Thread ausgeführt wird, werden sie das Parsen von HTML nicht blockieren, richtig? jedoch sind der JS-Engine-Thread und der GUI-Render-Thread gegenseitig ausschließend. Also, wenn der JS-Engine-Thread JS-Code ausführt, wird der GUI-Render-Thread, der das HTML analysiert, blockiert.

0 Stimmen

Beide werden den Parser nicht unterbrechen. Dies ist falsch, das Parsen würde im Falle von async blockiert werden.

20voto

dev Punkte 2054

Gute Praxis ist es, alle Dateien in Ihrem Quellordner zu halten, um Quelldateien schnell zu laden. Sie müssen alle Skript-, Stil-, Icon- und bildbezogenen Dateien herunterladen und diese Dateien in Ihren Projektordner legen.

Erstellen Sie diese Ordner in Ihrem Projekt, um verschiedene Quelldateien zu speichern, und laden Sie dann die erforderlichen Dateien aus diesen Ordnern in die Seiten.

js: um skriptbezogene Dateien zu halten.

css: um stilbezogene Dateien zu halten.

Bilder: um bild-/iconbezogene Dateien zu halten

Schriftarten: um schriftbezogene Dateien zu halten


Wann die defer und async Attribute auf dem </code> Tag zu verwenden</strong></p> <p><strong><code>defer</code> Attribut:</strong> Zuerst wird das <code>defer</code> Attribut die Skriptdatei herunterladen und dann auf das HTML-Parsing warten. Nach Abschluss des HTML-Parsing wird das Skript ausgeführt. Mit anderen Worten, es garantiert, dass alle Skripte nach dem HTML-Parsing ausgeführt werden.</p> <p>Das <code>defer</code> Attribut ist nützlich, wenn das Skript für DOM-Manipulationen verwendet wird.</p> <p><strong><code>async</code> Attribut:</strong> Das <code>async</code> Attribut wird die Skriptdatei herunterladen und ausführen, ohne auf das Ende des HTML-Parsing zu warten. Mit anderen Worten, es garantiert nicht, dass alle Skripte nach dem HTML-Parsing ausgeführt werden.</p> <p>Das <code>async</code> Attribut ist nützlich, wenn das Skript nicht für DOM-Manipulationen verwendet wird. Manchmal benötigen Sie ein Skript nur für serverseitige Operationen oder zur Behandlung von Cache oder Cookies, jedoch nicht für DOM-Manipulationen.</p> <p><a href="https://i.sstatic.net/pI1Wn.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/pI1Wn.png" alt="Geben Sie hier eine Bildbeschreibung ein" /></a></p> <hr /> <p>Nützlicher Link, wann defer und async zu verwenden sind: <a href="https://stackoverflow.com/a/68929270/7186739">https://stackoverflow.com/a/68929270/7186739</a></p></x-turndown>

1 Stimmen

0 Stimmen

Für Skripte und andere Ressourcen, die einzigartig für Ihre Website sind, ist dies ein guter Plan. Für gemeinsame Bibliotheken wie jQuery oder FontAwesome war ich jedoch der Meinung, dass es besser ist, ein CDN zu verwenden, da Browser möglicherweise bereits einige dieser Bibliotheken zwischengespeichert haben und sie daher erneut abrufen können überspringen. Ist das korrekt?

6voto

mjfneto Punkte 93

Ich denke, Jake Archibald hat uns bereits 2013 einige Erkenntnisse präsentiert, die dem Thema noch mehr Positivität verleihen könnten:

https://www.html5rocks.com/de/tutorials/speed/script-loading/

Der heilige Gral ist es, einen Satz von Skripten sofort herunterzuladen, ohne das Rendern zu blockieren und diese so schnell wie möglich in der Reihenfolge auszuführen, in der sie hinzugefügt wurden. Leider hasst dich HTML und lässt dich das nicht tun.

(...)

Die Antwort steht tatsächlich in der HTML5-Spezifikation, obwohl sie am Ende des Abschnitts über das Laden von Skripten versteckt ist. "Das async-IDL-Attribut steuert, ob das Element asynchron ausgeführt wird oder nicht. Wenn das "force-async"-Flag des Elements gesetzt ist, muss das async-IDL-Attribut beim Abrufen true zurückgeben und beim Setzen muss das "force-async"-Flag zuerst zurückgesetzt werden…".

(...)

Skripte, die dynamisch erstellt und dem Dokument hinzugefügt werden, sind standardmäßig asynchron, sie blockieren das Rendern nicht und werden sofort ausgeführt, sobald sie heruntergeladen sind, was bedeutet, dass sie in der falschen Reihenfolge ausgeführt werden könnten. Allerdings können wir sie explizit als nicht asynchron markieren:

[
    '//other-domain.com/1.js',
    '2.js'
].forEach(function(src) {
    var script = document.createElement('script');
    script.src = src;
    script.async = false;
    document.head.appendChild(script);
});

Das gibt unseren Skripten eine Mischung aus Verhalten, die nicht mit reinem HTML erreicht werden kann. Indem sie explizit nicht asynchron sind, werden Skripte einer Ausführungswarteschlange hinzugefügt, derselben Warteschlange, in die sie auch in unserem ersten plain-HTML-Beispiel hinzugefügt wurden. Allerdings werden sie durch ihre dynamische Erstellung außerhalb des Dokumentenparsings ausgeführt, sodass das Rendern nicht blockiert wird, während sie heruntergeladen werden (verwechseln Sie das Laden von nicht-asynchronen Skripten nicht mit sync XHR, was nie eine gute Sache ist).

Das obige Skript sollte direkt im Kopfbereich der Seiten eingefügt werden, um das Herunterladen von Skripten so schnell wie möglich ohne Unterbrechung des progressiven Renderings zu planen und so schnell wie möglich in der von Ihnen angegebenen Reihenfolge auszuführen. "2.js" kann vor "1.js" heruntergeladen werden, wird jedoch erst ausgeführt, wenn "1.js" entweder erfolgreich heruntergeladen und ausgeführt wurde oder fehlschlägt, beides zu tun. Hurra! async-Download, aber geordnete Ausführung!

Doch das könnte nicht der schnellste Weg sein, um Skripte zu laden:

(...) Mit dem obigen Beispiel muss der Browser Skript parsen und ausführen, um festzustellen, welche Skripte heruntergeladen werden sollen. Dadurch werden Ihre Skripte vor Preload-Scannern versteckt. Browser nutzen diese Scanner, um Ressourcen auf Seiten zu entdecken, die Sie wahrscheinlich als nächstes besuchen werden, oder um Seitenressourcen zu entdecken, während der Parser durch eine andere Ressource blockiert ist.

Wir können die Auffindbarkeit wiederherstellen, indem wir dies in den Kopf des Dokuments einfügen:

Dies teilt dem Browser mit, dass die Seite 1.js und 2.js benötigt. link[rel=subresource] ist ähnlich wie link[rel=prefetch], aber mit unterschiedlichen Semantiken. Leider wird es derzeit nur von Chrome unterstützt, und Sie müssen deklarieren, welche Skripte zweimal geladen werden sollen, einmal über Link-Elemente und erneut in Ihrem Skript.

Korrektur: Ich habe ursprünglich behauptet, dass diese vom Preload-Scanner erfasst wurden, was nicht der Fall ist. Sie werden vom regulären Parser erfasst. Allerdings könnte der Preload-Scanner diese erfassen, er tut es derzeit jedoch noch nicht, während Skripte, die von ausführbarem Code eingebunden werden, niemals vorab geladen werden können. Danke an Yoav Weiss, der mich in den Kommentaren korrigiert hat.

4voto

Der Rendering-Motor durchläuft mehrere Schritte, bis er etwas auf dem Bildschirm darstellt.

Es sieht so aus:

  1. HTML-Bytes in Zeichen umwandeln, abhängig von der Codierung, die wir für das Dokument festgelegt haben;
  2. Token werden entsprechend den Zeichen erstellt. Tokens bedeuten, Zeichen analysieren und Öffnen von Tags und verschachtelte Tags festlegen;
  3. Aus den Tokens werden getrennte Knoten erstellt. Sie sind Objekte und basierend auf den vom Tokenisierungsprozess bereitgestellten Informationen erstellt der Motor Objekte, die alle notwendigen Informationen zu jedem Knoten enthalten;
  4. Danach wird der DOM erstellt. DOM ist eine Baumdatenstruktur und repräsentiert die gesamte Hierarchie und Informationen über Beziehungen und Spezifikationen von Tags;

Der gleiche Prozess gilt für CSS. Für CSS erstellt der Rendering-Motor eine andere/getrennte Datenstruktur für CSS, die jedoch als CSSOM (CSS-Objektmodell) bezeichnet wird

Der Browser arbeitet nur mit Objektmodellen, daher muss er alle Informationen über DOM und CSSDOM kennen.

Der nächste Schritt besteht darin, den DOM und CSSOM irgendwie zu kombinieren. Denn ohne CSSOM weiß der Browser während des Renderingprozesses nicht, wie er jedes Element stylen soll.

All die obigen Informationen bedeuten, dass alles, was Sie in Ihrem HTML bereitstellen (Javascript, CSS), den DOM-Erstellungsprozess des Browsers anhält. Wenn Sie mit der Ereignisschleife vertraut sind, gibt es eine einfache Regel, wie die Ereignisschleife Aufgaben ausführt:

  1. Makroaufgaben ausführen;
  2. Mikroaufgaben ausführen;
  3. Rendering;

Wenn Sie also eine Javascript-Datei bereitstellen, weiß der Browser nicht, was der JS-Code tun wird, und stoppt den gesamten DOM-Erstellungsprozess und der Javascript-Interpreter beginnt mit dem Parsen und Ausführen des Javascript-Codes.

Auch wenn Sie Javascript ans Ende des Body-Tags legen, wird der Browser alle oben genannten Schritte für HTML und CSS durchführen, aber das Rendering wird ausgelassen. Er wird das Skript-Tag finden und erst dann weitermachen, wenn JS fertig ist.

Aber HTML bietet zwei zusätzliche Optionen für das Skript-Tag: async und defer.

Async - bedeutet, den Code ausführen, wenn er heruntergeladen wurde, und den DOM-Erstellungsprozess während des Herunterladens nicht blockieren.

Defer - bedeutet, den Code nach dem Herunterladen ausführen, wenn der Browser mit dem DOM-Erstellungs- und Renderingprozess fertig ist.

2voto

Himanshu Punkte 11
  1. Standard - Standardmäßig lädt der Browser beim Erkennen eines Skript-Tags die Datei herunter und führt sie dann aus. Die Skriptdateien werden in der Reihenfolge ihrer Platzierung ausgeführt.

  2. async - Der Browser lädt die Skriptdatei herunter und setzt das Parsen des HTML parallel fort, bis die Datei heruntergeladen ist. Die Datei wird sofort ausgeführt, sobald sie heruntergeladen ist.

  3. defer - Der Browser lädt das Skript herunter und führt gleichzeitig das HTML-Parsing durch. Nach Abschluss des Parsings werden die Skriptdateien in der Reihenfolge ihrer Platzierung ausgeführt.

Hinweis: Bei "defer" werden die JavaScript-Dateien in der Reihenfolge ihrer Platzierung im HTML-Dokument ausgeführt, während im Falle des Attributs "async" die Skriptdateien entsprechend ihrer Download-Zeit ausgeführt werden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X