1900 Stimmen

Wo sollte ich <script>-Tags in HTML-Markup einfügen?

Wenn Sie JavaScript in ein HTML-Dokument einbetten, wo ist der richtige Platz für die <script> Tags und eingebundenes JavaScript? Ich glaube mich zu erinnern, dass man diese nicht in die <head> Abschnitt, sondern am Anfang der <body> Abschnitt ist ebenfalls schlecht, da das JavaScript geparst werden muss, bevor die Seite vollständig gerendert wird (oder so ähnlich). Dies scheint die Ende der <body> Abschnitt als logischen Ort für <script> Tags.

Also, wo es der richtige Ort für die Unterbringung der <script> Tags?

(Diese Frage bezieht sich auf diese Frage in der vorgeschlagen wurde, dass JavaScript-Funktionsaufrufe von <a> Tags zu <script> Tags. Ich bin speziell mit jQuery, aber allgemeinere Antworten sind auch angemessen).

1 Stimmen

Falls du auch nur nach einer einfachen Lösung suchst und einen serverseitigen Generator wie Jekyll verwendest, empfehle ich dir, das Skript mit einzubinden. Das ist viel einfacher!

3 Stimmen

Wenn Sie von einer Suchmaschine kommen und danach suchen: Viele der Antworten sind nicht eindeutig genau die Stelle, an der das "Skript-Tag" am Ende stehen sollte . Wenn das "script"-Tag après </body>', führt die HTML-Validierung zu folgenden Ergebnissen _" Fehler: Skript mit falschem Start-Tag " (Option ankreuzen "Quelle" und klicken Sie "prüfen"_ um den HTML-Quelltext zu sehen). Es sollte sein antes de </body>'. (Das Ergebnis ist ähnlich, wenn das "script"-Tag ganz am Ende steht, nach dem </html> Tag.)

1 Stimmen

2386voto

Bart Punkte 24705

So sieht es aus, wenn ein Browser eine Website lädt, die eine <script> Schildchen an:

  1. Holen Sie die HTML-Seite (z. B. index.html )
  2. Mit dem Parsen des HTML beginnen
  3. Der Parser stößt auf eine <script> Tag, das auf eine externe Skriptdatei verweist.
  4. Der Browser fordert die Skriptdatei an. In der Zwischenzeit blockiert der Parser den anderen HTML-Code auf Ihrer Seite und hält ihn an.
  5. Nach einiger Zeit wird das Skript heruntergeladen und anschließend ausgeführt.
  6. Der Parser fährt mit dem Parsen des restlichen HTML-Dokuments fort.

Schritt Nr. 4 verursacht eine schlechte Benutzererfahrung. Ihre Website wird im Grunde nicht mehr geladen, bis Sie alle Skripte heruntergeladen haben. Wenn es etwas gibt, das Nutzer hassen, dann ist es das Warten auf das Laden einer Website.

Wie kommt es überhaupt dazu?

Jedes Skript kann sein eigenes HTML über document.write() oder andere DOM-Manipulationen. Dies bedeutet, dass der Parser warten muss, bis das Skript heruntergeladen und ausgeführt wurde, bevor er den Rest des Dokuments sicher parsen kann. Schließlich ist das Skript könnte sein eigenes HTML in das Dokument eingefügt hat.

Die meisten JavaScript-Entwickler manipulieren jedoch nicht mehr das DOM während das Dokument wird geladen. Stattdessen warten sie, bis das Dokument geladen ist, bevor sie es ändern. Zum Beispiel:

<!-- index.html -->
<html>
    <head>
        <title>My Page</title>
        <script src="my-script.js"></script>
    </head>
    <body>
        <div id="user-greeting">Welcome back, user</div>
    </body>
</html>

JavaScript:

// my-script.js
document.addEventListener("DOMContentLoaded", function() {
    // this function runs when the DOM is ready, i.e. when the document has been parsed
    document.getElementById("user-greeting").textContent = "Welcome back, Bart";
});

Weil Ihr Browser nicht weiß mein-skript.js das Dokument erst dann ändert, wenn es heruntergeladen und ausgeführt wurde, stellt der Parser das Parsen ein.

Antiquierte Empfehlung

Der alte Ansatz, dieses Problem zu lösen, bestand darin, die <script> Tags am unteren Rand Ihrer <body> denn so wird sichergestellt, dass der Parser nicht bis zum Ende blockiert wird.

Dieser Ansatz hat sein eigenes Problem: Der Browser kann mit dem Herunterladen der Skripte erst beginnen, wenn das gesamte Dokument geparst ist. Bei größeren Websites mit umfangreichen Skripten und Stylesheets ist es für die Leistung sehr wichtig, das Skript so schnell wie möglich herunterladen zu können. Wenn Ihre Website nicht innerhalb von 2 Sekunden geladen ist, werden die Besucher auf eine andere Website wechseln.

Bei einer optimalen Lösung würde der Browser so schnell wie möglich mit dem Herunterladen Ihrer Skripte beginnen, während er gleichzeitig den Rest Ihres Dokuments parst.

Der moderne Ansatz

Heute unterstützen die Browser die async y defer Attribute für Skripte. Diese Attribute teilen dem Browser mit, dass das Parsing sicher ist, während die Skripte heruntergeladen werden.

asynchron

<script src="path/to/script1.js" async></script>
<script src="path/to/script2.js" async></script>

Skripte mit dem Attribut async werden asynchron ausgeführt. Das bedeutet, dass das Skript ausgeführt wird, sobald es heruntergeladen wurde, ohne dass der Browser in der Zwischenzeit blockiert wird. Dies bedeutet, dass es möglich ist, dass Skript 2 vor Skript 1 heruntergeladen und ausgeführt wird.

Selon http://caniuse.com/#feat=script-async 97,78 % aller Browser unterstützen dies.

aufschieben.

<script src="path/to/script1.js" defer></script>
<script src="path/to/script2.js" defer></script>

Skripte mit dem Attribut "aufschieben" werden in der Reihenfolge ausgeführt (d. h. erst Skript 1, dann Skript 2). Auch dadurch wird der Browser nicht blockiert.

Im Gegensatz zu asynchronen Skripten werden aufgeschobene Skripte erst dann ausgeführt, wenn das gesamte Dokument geladen ist.

Selon http://caniuse.com/#feat=script-defer 97,79 % aller Browser unterstützen dies. 98,06 % unterstützen es zumindest teilweise.

Ein wichtiger Hinweis zur Browserkompatibilität: Unter Umständen können Internet Explorer 9 und frühere Versionen zeitversetzte Skripte nicht in der richtigen Reihenfolge ausführen. Wenn Sie diese Browser unterstützen müssen, lesen Sie bitte este zuerst!

(Um mehr zu erfahren und einige wirklich hilfreiche visuelle Darstellungen der Unterschiede zwischen asynchronen, aufgeschobenen und normalen Skripten zu sehen, lesen Sie die ersten beiden Links im Abschnitt Referenzen dieser Antwort)

Schlussfolgerung

Der derzeitige Stand der Technik ist es, Skripte in der <head> Tag verwenden und das async o defer Eigenschaften. Dadurch können Ihre Skripte so schnell wie möglich heruntergeladen werden, ohne dass Ihr Browser blockiert wird.

Das Gute daran ist, dass Ihre Website auch auf den 2 % der Browser, die diese Attribute nicht unterstützen, korrekt geladen wird, während die anderen 98 % schneller werden.

Referenzen

0 Stimmen

Mit dieser Methode, was wäre der beste Weg, um Javascript ausführen, nachdem alle js-Dateien geladen sind? Derzeit verwende ich das onload-Ereignis innerhalb des öffnenden Body-Tags.

0 Stimmen

Hat jemand eine Meinung zu diesem Ansatz? feedthebot.com/pagespeed/defer-loading-javascript.html

0 Stimmen

Ich kann mir nicht wirklich vorstellen, viele Szenarien, in denen DOM nicht durch JavaScript geändert wird. Könnte jemand ein Beispiel für ein Skript, das verwenden würde, geben async ?

255voto

Cammel Punkte 2603

Kurz vor dem abschließenden Body-Tag, wie unter _Skripte unten anbringen_ :

Skripte unten anbringen

Das Problem, das durch Skripte verursacht wird, ist, dass sie parallele Downloads blockieren. Die HTTP/1.1-Spezifikation schlägt vor, dass die Browser nicht mehr als zwei Komponenten pro Hostname parallel herunterladen. Wenn Sie Ihre Bilder von mehreren Hostnamen aus bereitstellen, können Sie erreichen, dass mehr als zwei Downloads parallel stattfinden. Während ein Skript heruntergeladen wird, startet der Browser jedoch keine weiteren Downloads, auch nicht unter anderen Hostnamen.

7 Stimmen

Ich bin mit dem Konzept und seiner Erläuterung einverstanden. Aber was passiert, wenn der Benutzer beginnt, mit der Seite zu spielen. Nehmen wir an, ich habe ein AJAX-Dropdown, das zu laden beginnt, nachdem die Seite dem Benutzer angezeigt wurde, aber während es geladen wird, klickt der Benutzer darauf! Und was passiert, wenn ein "wirklich ungeduldiger" Benutzer das Formular ausfüllt?

9 Stimmen

@Hermant Alter Kommentar, aber Sie können den Trick tun, deaktivieren Sie die Felder standardmäßig dann aktivieren sie mit JS, wenn das DOM vollständig geladen ist. Das ist es, was Facebook heutzutage zu tun scheint.

2 Stimmen

Ich habe das gerade mit Chrome getestet, um zu sehen, ob es immer noch dasselbe ist. Es ist. Sie können die Unterschiede in der Seitenladezeit Ihrer Browser hier überprüfen. stevesouders.com/cuzillion

103voto

Salman A Punkte 246207

Nicht blockierende Skript-Tags können fast überall platziert werden:

<script src="script.js" async></script>
<script src="script.js" defer></script>
<script src="script.js" async defer></script>
  • async das Skript wird asynchron ausgeführt, sobald es verfügbar ist
  • defer Skript wird ausgeführt, wenn das Dokument fertig geparst ist
  • async defer das Skript greift auf das Aufschiebeverhalten zurück, wenn async nicht unterstützt wird

Solche Skripte werden asynchron/nach Fertigstellung des Dokuments ausgeführt, was bedeutet, dass Sie dies nicht tun können:

<script src="jquery.js" async></script>
<script>jQuery(something);</script>
<!--
  * might throw "jQuery is not defined" error
  * defer will not work either
-->

Oder dies:

<script src="document.write(something).js" async></script>
<!--
  * might issue "cannot write into document from an asynchronous script" warning
  * defer will not work either
-->

Oder dies:

<script src="jquery.js" async></script>
<script src="jQuery(something).js" async></script>
<!--
  * might throw "jQuery is not defined" error (no guarantee which script runs first)
  * defer will work in sane browsers
-->

Oder dies:

<script src="document.getElementById(header).js" async></script>
<div id="header"></div>
<!--
  * might not locate #header (script could fire before parser looks at the next line)
  * defer will work in sane browsers
-->

Allerdings bieten asynchrone Skripte diese Vorteile:

  • Paralleler Download von Ressourcen :
    Der Browser kann Stylesheets, Bilder und andere Skripte parallel herunterladen, ohne darauf zu warten, dass ein Skript heruntergeladen und ausgeführt wird.
  • Unabhängigkeit der Quellbestellung :
    Sie können die Skripte in head oder body platzieren, ohne sich Gedanken über Blockierungen zu machen (nützlich, wenn Sie ein CMS verwenden). Die Ausführungsreihenfolge ist aber immer noch wichtig.

Es ist möglich, die Probleme mit der Ausführungsreihenfolge zu umgehen, indem man externe Skripte verwendet, die Callbacks unterstützen. Viele JavaScript-APIs von Drittanbietern unterstützen jetzt die nicht-blockierende Ausführung. Hier ist ein Beispiel für das asynchrone Laden der Google Maps API .

2 Stimmen

Dies ist die richtige Antwort für heute - mit diesem Ansatz ist es einfacher, Ihre Widgets in sich geschlossen zu halten, keine Notwendigkeit, ausgefallene <head> Logik einschließen.

1 Stimmen

Ich bin verwirrt, warum Sie nicht verwenden können async ou defer wenn Sie jQuery einschließen, wie Sie in Ihrem zweiten Block angeben: <script src="jquery.js" async></script> . Können Sie erklären, warum? Ich dachte, ich brauche, um die async-Tag in für Performance-per die akzeptierte Antwort-so meine Seite laden kann, auch während jQuery noch geladen wird]. Vielen Dank!

3 Stimmen

@elbow 99% der Zeit <script src=jquery.js> wird gefolgt von $(function(){ ... }) Blöcke irgendwo auf der Seite. Asynchrones Laden garantiert nicht, dass jQuery zu dem Zeitpunkt geladen wird, an dem der Browser versucht, diese Blöcke zu parsen, daher wird $ ist nicht definiert Fehler (Sie erhalten den Fehler möglicherweise nicht, wenn jQuery aus dem Cache geladen wurde). Ich beantwortete eine Frage über das asynchrone Laden von jQuery und die Erhaltung $(function(){ ... }) . Ich werde sehen, ob ich sie finden kann, oder Sie können sich diese Frage ansehen: stackoverflow.com/q/14811471/87015

42voto

orip Punkte 69138

Der Standardratschlag, der vom Yahoo! Exceptional Performance Team gefördert wird, lautet, die <script> Tags am Ende des Dokumentkörpers, damit sie das Rendern der Seite nicht blockieren.

Es gibt jedoch einige neuere Ansätze, die eine bessere Leistung bieten, wie in diese Antwort über die Ladezeit der Google Analytics JavaScript-Datei:

Es gibt einige tolle Dias von Steve Souders (Experte für Client-seitige Leistung) über:

  • Verschiedene Techniken zum parallelen Laden externer JavaScript-Dateien
  • ihre Auswirkungen auf die Ladezeit und die Darstellung der Seite
  • welche Art von Fortschrittsanzeigen der Browser anzeigt (z. B. "Laden" in der Statusleiste, Sanduhr-Mauszeiger).

1 Stimmen

Re "am Ende des Dokumentkörpers" : Vor das abschließende Body-Tag ( </body> ), vermutlich? Können Sie das deutlicher machen? (Aber ohne "Bearbeiten:", "Aktualisieren:" oder ähnlich - die Antwort sollte so aussehen, als wäre sie heute geschrieben worden).

1 Stimmen

(Steve Souders ist nicht zu verwechseln mit Steve Saunders oder John Saunders .)

39voto

cquezel Punkte 3043

Der moderne Ansatz im Jahr 2019 ist die Verwendung von Skripten des Modultyps ES6 .

<script type="module" src="..."></script>

Standardmäßig werden Module asynchron und zeitversetzt geladen, d. h. Sie können sie an beliebiger Stelle platzieren und sie werden parallel geladen und ausgeführt, wenn die Seite fertig geladen ist.

Die Unterschiede zwischen einem Skript und einem Modul werden hier beschrieben:

Klassische Skripte vs. Modulskripte in JavaScript

Die Ausführung eines Moduls im Vergleich zu einem Skript wird hier beschrieben:

Module werden standardmäßig zurückgestellt

Die Unterstützung wird hier angezeigt:

Kann ich... Unterstützung von Tabellen für HTML5, CSS3, etc.

0 Stimmen

Gute Informationen zur Erweiterung der Wissensbasis

6 Stimmen

Beachten Sie bitte, dass dies nicht funktioniert, wenn Sie nur auf Ihrem lokalen Dateisystem ohne Server testen wollen. Zumindest auf Chrome erhalten Sie eine Cross-Origin-Fehler versuchen, die js aus dem HTML zu laden, obwohl sie beide den gleichen Ursprung haben, Ihr Dateisystem.

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