Es gibt so viele verschiedene Möglichkeiten, JavaScript in eine HTML-Seite aufzunehmen. Ich kenne die folgenden Optionen:
- Inline-Code oder von einem externen URI geladen
- im <head> - oder <body> -Tag enthalten [ 1 , 2 ]
- mit keinem
defer
oderasync
Attribut (nur externe Skripte) - in der statischen Quelle enthalten oder dynamisch von anderen Skripten hinzugefügt (in unterschiedlichen Analysezuständen, mit unterschiedlichen Methoden)
Ohne Browserskripte von der Festplatte, Javascript: URIs und onEvent
-attributes [ 3 ], gibt es bereits 16 Alternativen, um JS auszuführen , und ich bin sicher, dass ich etwas vergessen habe.
Ich bin nicht so sehr mit dem schnellen (parallelen) Laden beschäftigt, sondern eher neugierig auf die Ausführungsreihenfolge (die von der Ladereihenfolge und der Dokumentreihenfolge abhängen kann ). Gibt es eine gute (browserübergreifende) Referenz, die wirklich alle Fälle abdeckt? ZB http://www.websiteoptimization.com/speed/tweak/defer/ befasst sich nur mit 6 von ihnen und testet meistens alte Browser.
Da ich befürchte, dass dies nicht der Fall ist, ist hier meine spezielle Frage: Ich habe einige (externe) Head-Skripte zum Initialisieren und Laden von Skripten. Dann habe ich zwei statische Inline-Skripte am Ende des Körpers. Mit dem ersten kann der Skriptlader ein anderes Skriptelement (das auf externe js verweist) dynamisch an den Body anhängen. Das zweite der statischen Inline-Skripte möchte js aus dem hinzugefügten externen Skript verwenden. Kann es sich darauf verlassen, dass der andere hingerichtet wurde (und warum :-)?
quelle
Antworten:
Wenn Sie nicht dynamisch Scripts geladen werden oder markieren sie als
defer
oderasync
werden dann Skripts in der Reihenfolge , in der Seite aufgetreten geladen. Es spielt keine Rolle, ob es sich um ein externes Skript oder ein Inline-Skript handelt - sie werden in der Reihenfolge ausgeführt, in der sie auf der Seite vorkommen. Inline-Skripte, die nach externen Skripten kommen, werden gehalten, bis alle externen Skripte, die vor ihnen kamen, geladen und ausgeführt wurden.Asynchrone Skripte (unabhängig davon, wie sie als asynchron angegeben werden) werden geladen und in einer unvorhersehbaren Reihenfolge ausgeführt. Der Browser lädt sie parallel und kann sie in beliebiger Reihenfolge ausführen.
Es gibt keine vorhersehbare Reihenfolge zwischen mehreren asynchronen Dingen. Wenn eine vorhersehbare Reihenfolge benötigt wird, muss diese codiert werden, indem für Ladebenachrichtigungen aus den asynchronen Skripten registriert und Javascript-Aufrufe manuell sequenziert werden, wenn die entsprechenden Dinge geladen werden.
Wenn ein Skript-Tag dynamisch eingefügt wird, hängt das Verhalten der Ausführungsreihenfolge vom Browser ab. In diesem Referenzartikel können Sie sehen, wie sich Firefox verhält . Kurz gesagt, die neueren Versionen von Firefox verwenden standardmäßig ein dynamisch hinzugefügtes Skript-Tag zu asynchron, sofern das Skript-Tag nicht anders festgelegt wurde.
Ein Skript-Tag mit
async
kann ausgeführt werden, sobald es geladen wird. Tatsächlich kann der Browser den Parser von allen anderen Aktionen anhalten und das Skript ausführen. Es kann also wirklich fast jederzeit ausgeführt werden. Wenn das Skript zwischengespeichert wurde, wird es möglicherweise fast sofort ausgeführt. Wenn das Laden des Skripts eine Weile dauert, wird es möglicherweise ausgeführt, nachdem der Parser fertig ist. Das einzige, woran Sie sich erinnern sollten,async
ist, dass es jederzeit ausgeführt werden kann und diese Zeit nicht vorhersehbar ist.Ein Skript-Tag mit
defer
wartet, bis der gesamte Parser fertig ist, und führt dann alle Skripte aus, die mitdefer
in der Reihenfolge markiert sind, in der sie angetroffen wurden. Auf diese Weise können Sie mehrere voneinander abhängige Skripte als markierendefer
. Sie werden alle verschoben, bis der Dokumentparser fertig ist, aber sie werden in der Reihenfolge ausgeführt, in der sie angetroffen wurden, wobei ihre Abhängigkeiten erhalten bleiben. Ich denke,defer
als würden die Skripte in eine Warteschlange gestellt, die nach Abschluss des Parsers verarbeitet wird. Technisch gesehen kann der Browser die Skripte jederzeit im Hintergrund herunterladen, aber sie werden den Parser erst ausführen oder blockieren, nachdem der Parser die Seite analysiert und Inline-Skripte analysiert und ausgeführt hat, die nicht markiert sinddefer
oderasync
.Hier ist ein Zitat aus diesem Artikel:
Der relevante Teil der HTML5-Spezifikation (für neuere kompatible Browser) ist hier . Dort ist viel über asynchrones Verhalten geschrieben. Offensichtlich gilt diese Spezifikation nicht für ältere Browser (oder fehlerhafte Browser), deren Verhalten Sie wahrscheinlich testen müssten, um festzustellen.
Ein Zitat aus der HTML5-Spezifikation:
Was ist mit Javascript-Modul-Skripten
type="module"
?Javascript unterstützt jetzt das Laden von Modulen mit folgender Syntax:
Oder mit
src
Attribut:Alle Skripte mit
type="module"
erhalten automatisch dasdefer
Attribut. Dadurch werden sie parallel (wenn nicht inline) zum anderen Laden der Seite heruntergeladen und anschließend in der angegebenen Reihenfolge ausgeführt, jedoch nachdem der Parser fertig ist.Modulskripten kann auch das
async
Attribut zugewiesen werden, mit dem Inline-Modulskripte so schnell wie möglich ausgeführt werden. Sie warten nicht, bis der Parser fertig ist, und warten nicht darauf, dasasync
Skript in einer bestimmten Reihenfolge im Vergleich zu anderen Skripten auszuführen .Es gibt ein ziemlich nützliches Zeitdiagramm, das das Abrufen und Ausführen verschiedener Kombinationen von Skripten zeigt, einschließlich Modulskripten hier in diesem Artikel: Laden von Javascript- Modulen .
quelle
defer
der Parser den Download früher starten und gleichzeitig die Ausführung verschieben. Wenn Sie viele Skripte vom selben Host haben, kann ein früherer Start des Downloads das Herunterladen anderer Skripte vom selben Host verlangsamen (da diese um die Bandbreite konkurrieren), auf die Ihre Seite wartet (was nicht der Fall istdefer
) Dies könnte ein zweischneidiges Schwert sein.Der Browser führt die Skripte in der Reihenfolge aus, in der er sie findet. Wenn Sie ein externes Skript aufrufen, wird die Seite blockiert, bis das Skript geladen und ausgeführt wurde.
Um diese Tatsache zu testen:
Dynamisch hinzugefügte Skripte werden ausgeführt, sobald sie an das Dokument angehängt werden.
Um diese Tatsache zu testen:
Die Reihenfolge der Warnungen ist "angehängt" -> "Hallo!" -> "final"
Wenn Sie in einem Skript versuchen, auf ein Element zuzugreifen, das noch nicht erreicht wurde (Beispiel
<script>do something with #blah</script><div id="blah"></div>
:), wird eine Fehlermeldung angezeigt.Insgesamt können Sie ja externe Skripte einschließen und dann auf deren Funktionen und Variablen zugreifen, aber nur, wenn Sie das aktuelle
<script>
Tag beenden und ein neues starten.quelle
Eine großartige Zusammenfassung von @addyosmani
Schamlos kopiert von https://addyosmani.com/blog/script-priorities/
quelle
Nach dem Testen vieler Optionen habe ich festgestellt, dass die folgende einfache Lösung darin besteht, die dynamisch geladenen Skripte in der Reihenfolge zu laden, in der sie in allen modernen Browsern hinzugefügt werden
quelle