Lade- und Ausführungsreihenfolge einer Webseite?


244

Ich habe einige webbasierte Projekte durchgeführt, denke aber nicht zu viel über die Lade- und Ausführungsreihenfolge einer normalen Webseite nach. Aber jetzt muss ich Details wissen. Es ist schwierig, Antworten von Google oder SO zu finden, daher habe ich diese Frage erstellt.

Eine Beispielseite sieht folgendermaßen aus:

<html>
 <head>
  <script src="jquery.js" type="text/javascript"></script>
  <script src="abc.js" type="text/javascript">
  </script>
  <link rel="stylesheets" type="text/css" href="abc.css"></link>
  <style>h2{font-wight:bold;}</style>
  <script>
  $(document).ready(function(){
     $("#img").attr("src", "kkk.png");
  });
 </script>
 </head>
 <body>
    <img id="img" src="abc.jpg" style="width:400px;height:300px;"/>
    <script src="kkk.js" type="text/javascript"></script>
 </body>
</html>

Also hier sind meine Fragen:

  1. Wie wird diese Seite geladen?
  2. Wie ist die Reihenfolge des Ladens?
  3. Wann wird der JS-Code ausgeführt? (Inline und Extern)
  4. Wann wird das CSS ausgeführt (angewendet)?
  5. Wann wird $ (document) .ready ausgeführt?
  6. Wird abc.jpg heruntergeladen? Oder lädt es einfach kkk.png herunter?

Ich habe folgendes Verständnis:

  1. Der Browser lädt zuerst das HTML (DOM).
  2. Der Browser beginnt, die externen Ressourcen Zeile für Zeile von oben nach unten zu laden.
  3. Wenn a <script>erfüllt ist, wird das Laden blockiert und warten, bis die JS-Datei geladen und ausgeführt wird, und dann fortfahren.
  4. Andere Ressourcen (CSS / Bilder) werden parallel geladen und bei Bedarf ausgeführt (wie CSS).

Oder ist es so:

Der Browser analysiert das HTML (DOM) und ruft die externen Ressourcen in einem Array oder einer stapelartigen Struktur ab. Nachdem das HTML geladen wurde, beginnt der Browser, die externen Ressourcen in der Struktur parallel zu laden und auszuführen, bis alle Ressourcen geladen sind. Dann wird das DOM entsprechend dem JS entsprechend dem Verhalten des Benutzers geändert.

Kann jemand eine detaillierte Erklärung geben, was passiert, wenn Sie die Antwort einer HTML-Seite erhalten? Unterscheidet sich dies in verschiedenen Browsern? Irgendwelche Hinweise zu dieser Frage?

Vielen Dank.

BEARBEITEN:

Ich habe in Firefox ein Experiment mit Firebug durchgeführt. Und es zeigt sich wie folgt: Alt-Text


11
Steve Souders hat auf diesem Gebiet viel Arbeit geleistet. Google für Steve + Souders + High + Performance und schauen Sie.
anddoutoi

3
Ich meine nicht Performance-Tuning. Ich möchte das Detail wissen.
Zhu Tao

2
Durch das Lesen seiner Arbeit hat sich mein Verständnis, wie "es" im Detail funktioniert, verzehnfacht, so dass es immer noch ein gültiger Kommentar ist. Es ist mir aus urheberrechtlichen Gründen nicht gestattet, sein gesamtes Buch hier zu zitieren, daher schlage ich vor, dass Sie seine Arbeit nachschlagen.
anddoutoi

3
Eine gute Beschreibung der Reihenfolge, in der die Dinge geschehen, finden Sie hier
Gerrat,

Antworten:


277

Nach Ihrer Stichprobe,

<html>
 <head>
  <script src="jquery.js" type="text/javascript"></script>
  <script src="abc.js" type="text/javascript">
  </script>
  <link rel="stylesheets" type="text/css" href="abc.css"></link>
  <style>h2{font-wight:bold;}</style>
  <script>
  $(document).ready(function(){
     $("#img").attr("src", "kkk.png");
  });
 </script>
 </head>
 <body>
    <img id="img" src="abc.jpg" style="width:400px;height:300px;"/>
    <script src="kkk.js" type="text/javascript"></script>
 </body>
</html>

Der Ausführungsfluss ist ungefähr wie folgt:

  1. Das HTML-Dokument wird heruntergeladen
  2. Das Parsen des HTML-Dokuments beginnt
  3. HTML-Analyse erreicht <script src="jquery.js" ...
  4. jquery.js wird heruntergeladen und analysiert
  5. HTML-Analyse erreicht <script src="abc.js" ...
  6. abc.js wird heruntergeladen, analysiert und ausgeführt
  7. HTML-Analyse erreicht <link href="abc.css" ...
  8. abc.css wird heruntergeladen und analysiert
  9. HTML-Analyse erreicht <style>...</style>
  10. Interne CSS-Regeln werden analysiert und definiert
  11. HTML-Analyse erreicht <script>...</script>
  12. Internes Javascript wird analysiert und ausgeführt
  13. HTML-Analyse erreicht <img src="abc.jpg" ...
  14. abc.jpg wird heruntergeladen und angezeigt
  15. HTML-Analyse erreicht <script src="kkk.js" ...
  16. kkk.js wird heruntergeladen, analysiert und ausgeführt
  17. Das Parsen des HTML-Dokuments wird beendet

Beachten Sie, dass der Download aufgrund des Verhaltens des Browsers möglicherweise asynchron und nicht blockierend ist. In Firefox gibt es beispielsweise diese Einstellung, die die Anzahl gleichzeitiger Anforderungen pro Domäne begrenzt.

Abhängig davon, ob die Komponente bereits zwischengespeichert wurde oder nicht, wird die Komponente möglicherweise in naher Zukunft nicht erneut angefordert. Wenn die Komponente zwischengespeichert wurde, wird die Komponente anstelle der tatsächlichen URL aus dem Cache geladen.

Wenn die Analyse beendet ist und das Dokument bereit und geladen ist, werden die Ereignisse onloadausgelöst. Wenn onloadalso abgefeuert wird, $("#img").attr("src","kkk.png");wird der ausgeführt. So:

  1. Dokument ist fertig, Onload wird ausgelöst.
  2. Javascript-Ausführungstreffer $("#img").attr("src", "kkk.png");
  3. kkk.png wird heruntergeladen und geladen in #img

Das $(document).ready()Ereignis ist tatsächlich das Ereignis, das ausgelöst wird, wenn alle Seitenkomponenten geladen und bereit sind. Lesen Sie mehr darüber: http://docs.jquery.com/Tutorials:Introducing_$ (document) .ready ()

Bearbeiten - In diesem Abschnitt wird mehr auf den parallelen oder nicht parallelen Teil eingegangen:

Standardmäßig und nach meinem derzeitigen Verständnis führt der Browser jede Seite normalerweise auf drei Arten aus: HTML-Parser, Javascript / DOM und CSS.

Der HTML-Parser ist für das Parsen und Interpretieren der Auszeichnungssprache verantwortlich und muss daher in der Lage sein, die beiden anderen Komponenten aufzurufen.

Zum Beispiel, wenn der Parser auf diese Zeile stößt:

<a href="#" onclick="alert('test');return false;" style="font-weight:bold">a hypertext link</a>

Der Parser führt drei Aufrufe durch, zwei an Javascript und einen an CSS. Zunächst erstellt der Parser dieses Element und registriert es im DOM-Namespace zusammen mit allen Attributen, die sich auf dieses Element beziehen. Zweitens ruft der Parser auf, um das Ereignis onclick an dieses bestimmte Element zu binden. Zuletzt wird der CSS-Thread erneut aufgerufen, um den CSS-Stil auf dieses bestimmte Element anzuwenden.

Die Ausführung erfolgt von oben nach unten und mit einem Thread. Javascript mag multithreaded aussehen, aber Tatsache ist, dass Javascript Single-Threaded ist. Aus diesem Grund wird beim Laden einer externen Javascript-Datei das Parsen der HTML-Hauptseite angehalten.

Die CSS-Dateien können jedoch gleichzeitig heruntergeladen werden, da CSS-Regeln immer angewendet werden. Dies bedeutet, dass Elemente immer mit den aktuellsten definierten CSS-Regeln neu gestrichen werden, wodurch die Blockierung aufgehoben wird.

Ein Element ist im DOM erst verfügbar, nachdem es analysiert wurde. Wenn Sie also mit einem bestimmten Element arbeiten, wird das Skript immer nach oder innerhalb des Fenster-Onload-Ereignisses platziert.

Ein solches Skript verursacht Fehler (in jQuery):

<script type="text/javascript">/* <![CDATA[ */
  alert($("#mydiv").html());
/* ]]> */</script>
<div id="mydiv">Hello World</div>

Denn wenn das Skript analysiert wird, ist das #mydivElement immer noch nicht definiert. Stattdessen würde dies funktionieren:

<div id="mydiv">Hello World</div>
<script type="text/javascript">/* <![CDATA[ */
  alert($("#mydiv").html());
/* ]]> */</script>

ODER

<script type="text/javascript">/* <![CDATA[ */
  $(window).ready(function(){
                    alert($("#mydiv").html());
                  });
/* ]]> */</script>
<div id="mydiv">Hello World</div>

4
Vielen Dank. Sie haben jedoch erwähnt, dass der Download aufgrund des Verhaltens des Browsers möglicherweise asynchron und nicht blockierend ist. Welche Art von Komponenten kann also in Asyn heruntergeladen werden (nehmen Sie FF als Instanz)? <script>blockiert andere Komponenten, richtig? Gibt es einen Verweis auf die Spezifikation für jeden Browser?
Zhu Tao

4
$ (document) .ready () wird ausgelöst, wenn das DOM vollständig ist, nicht wenn alle Seitenkomponenten geladen sind
Pierre

2
@Pierre nach Seitenkomponenten Ich meinte das DOM -> welche Komponenten auch immer im DOM.
Mauris

3
Nur um zu verdeutlichen, dass ... reguläres window.onload nach # 17 erfolgt ... also bei welchem ​​# wird der Code von jquery's $ (document) .ready () ausgeführt? # 12? aber das DOM selbst ist auf # 1 geladen, oder?
Armyofda12mnkeys

1
Wenn in der Registerkarte <body> ein <link href = "bootstrap.min.css" rel = "stylesheet" /> zwischen <img> und <script> hinzugefügt wird, wird img nicht angezeigt, bis bootrap heruntergeladen wird ... Ich denke also, Schritt [13], [14] müssen geändert werden ... kann jemand dieses Verhalten erklären?
Bhuvan

34

1) HTML wird heruntergeladen.

2) HTML wird schrittweise analysiert. Wenn eine Anforderung für ein Asset erreicht ist, versucht der Browser, das Asset herunterzuladen. Eine Standardkonfiguration für die meisten HTTP-Server und die meisten Browser besteht darin, nur zwei Anforderungen parallel zu verarbeiten. IE kann neu konfiguriert werden, um eine unbegrenzte Anzahl von Assets parallel herunterzuladen. Steve Souders konnte über 100 Anfragen parallel im IE herunterladen. Die Ausnahme besteht darin, dass Skriptanforderungen parallele Asset-Anforderungen im IE blockieren. Aus diesem Grund wird dringend empfohlen, das gesamte JavaScript in externe JavaScript-Dateien einzufügen und die Anforderung unmittelbar vor dem schließenden Body-Tag in den HTML-Code einzufügen.

3) Sobald der HTML-Code analysiert ist, wird das DOM gerendert. CSS wird in fast allen Benutzeragenten parallel zum Rendern des DOM gerendert. Aus diesem Grund wird dringend empfohlen, den gesamten CSS-Code in externen CSS-Dateien abzulegen, die im Abschnitt <head> </ head> des Dokuments so hoch wie möglich angefordert werden. Andernfalls wird die Seite bis zum Auftreten der CSS-Anforderungsposition im DOM gerendert, und das Rendern beginnt von oben.

4) Erst nachdem das DOM vollständig gerendert wurde und Anforderungen für alle Assets auf der Seite entweder aufgelöst wurden oder eine Zeitüberschreitung aufgetreten ist, wird JavaScript vom Onload-Ereignis ausgeführt. IE7, und ich bin mir bei IE8 nicht sicher, führt keine schnelle Zeitüberschreitung bei Assets durch, wenn keine HTTP-Antwort von der Asset-Anforderung empfangen wird. Dies bedeutet, dass ein von JavaScript inline auf der Seite angefordertes Asset, dh JavaScript, das in HTML-Tags geschrieben wird, die nicht in einer Funktion enthalten sind, die Ausführung des Onload-Ereignisses für Stunden verhindern kann. Dieses Problem kann ausgelöst werden, wenn ein solcher Inline-Code auf der Seite vorhanden ist und aufgrund einer Namespace-Kollision, die einen Code-Absturz verursacht, nicht ausgeführt werden kann.

Von den oben genannten Schritten ist das Parsen des DOM / CSS der CPU-intensivste. Wenn Sie möchten, dass Ihre Seite schneller verarbeitet wird, schreiben Sie effizientes CSS, indem Sie redundante Anweisungen eliminieren und CSS-Anweisungen in möglichst wenigen Elementreferenzen zusammenfassen. Wenn Sie die Anzahl der Knoten in Ihrem DOM-Baum verringern, wird auch das Rendern beschleunigt.

Beachten Sie, dass jedes Asset, das Sie von Ihrem HTML-Code oder sogar von Ihren CSS / JavaScript-Assets anfordern, mit einem separaten HTTP-Header angefordert wird. Dies verbraucht Bandbreite und erfordert die Verarbeitung pro Anforderung. Wenn Sie möchten, dass Ihre Seite so schnell wie möglich geladen wird, reduzieren Sie die Anzahl der HTTP-Anforderungen und die Größe Ihres HTML-Codes. Sie tun Ihrer Benutzererfahrung keinen Gefallen, indem Sie das Seitengewicht allein aus HTML auf 180 KB berechnen. Viele Entwickler bekennen sich zu einem Irrtum, dass sich ein Benutzer innerhalb von 6 Nanosekunden über die Qualität des Inhalts auf der Seite entscheidet und dann die DNS-Abfrage von seinem Server löscht und seinen Computer brennt, wenn er unzufrieden ist. Stattdessen bieten sie die schönste Seite unter 250k HTML. Halten Sie Ihren HTML-Code kurz und bündig, damit ein Benutzer Ihre Seiten schneller laden kann.


2
Konsolidieren von CSS-Anweisungen in möglichst wenigen Elementreferenzen Klingt komisch. Wenn ich drei Elemente formatieren muss, muss ich genau drei Elemente referenzieren. Ich kann eins nicht auf Stil zehn verweisen, oder? Oder erläutern Sie das
Green

12

Öffnen Sie Ihre Seite in Firefox und holen Sie sich das HTTPFox-Addon. Es wird Ihnen alles sagen, was Sie brauchen.

Gefunden auf archivist.incuito:

http://archivist.incutio.com/viewlist/css-discuss/76444

Wenn Sie zum ersten Mal eine Seite anfordern, sendet Ihr Browser eine GET-Anforderung an den Server, der den HTML-Code an den Browser zurückgibt. Der Browser beginnt dann mit dem Parsen der Seite (möglicherweise bevor alles zurückgegeben wurde).

Wenn ein Verweis auf eine externe Entität wie eine CSS-Datei, eine Bilddatei, eine Skriptdatei, eine Flash-Datei oder etwas anderes außerhalb der Seite gefunden wird (entweder auf demselben Server / derselben Domäne oder nicht), wird die Erstellung vorbereitet eine weitere GET-Anfrage für diese Ressource.

Der HTTP-Standard legt jedoch fest, dass der Browser nicht mehr als zwei gleichzeitige Anforderungen an dieselbe Domäne senden soll. Daher wird jede Anforderung an eine bestimmte Domäne in einer Warteschlange gestellt, und wenn jede Entität zurückgegeben wird, wird die nächste in der Warteschlange für diese Domäne gestartet.

Die Zeit, die für die Rückgabe einer Entität benötigt wird, hängt von ihrer Größe, der aktuellen Auslastung des Servers und der Aktivität jedes einzelnen Computers zwischen dem Computer, auf dem der Browser ausgeführt wird, und dem Server ab. Die Liste dieser Maschinen kann grundsätzlich für jede Anfrage unterschiedlich sein, sofern ein Bild von den USA über den Atlantik zu mir nach Großbritannien in Großbritannien gelangt, während ein anderes vom selben Server über den Pazifik, Asien und Europa ausgegeben wird. das dauert länger. Möglicherweise erhalten Sie eine Sequenz wie die folgende, in der eine Seite (in dieser Reihenfolge) Verweise auf drei Skriptdateien und fünf Bilddateien unterschiedlicher Größe enthält:

  1. GET script1 und script2; Warteschlangenanforderung für script3 und images1-5.
  2. script2 kommt an (es ist kleiner als script1): GET script3, queue images1-5.
  3. script1 kommt an; GET image1, queue images2-5.
  4. Bild1 kommt an, GET Bild2, Warteschlange Bilder3-5.
  5. script3 kommt aufgrund eines Netzwerkproblems nicht an - GET script3 erneut (automatische Wiederholung).
  6. Bild2 kommt an, Skript3 immer noch nicht hier; GET image3, queue images4-5.
  7. Bild 3 kommt an; GET image4, queue image5, script3 sind noch unterwegs.
  8. Bild4 kommt an, GET Bild5;
  9. image5 kommt an.
  10. script3 kommt an.

Kurz gesagt: Jede alte Bestellung, abhängig davon, was der Server tut, was der Rest des Internets tut und ob etwas fehlerhaft ist oder nicht und erneut abgerufen werden muss. Dies mag seltsam erscheinen, aber es wäre für das Internet (nicht nur für das WWW) buchstäblich unmöglich, mit einem gewissen Maß an Zuverlässigkeit zu arbeiten, wenn es nicht so gemacht würde.

Außerdem ruft die interne Warteschlange des Browsers möglicherweise keine Entitäten in der Reihenfolge ab, in der sie auf der Seite angezeigt werden - dies ist in keinem Standard erforderlich.

(Oh, und vergessen Sie nicht das Caching, sowohl im Browser als auch beim Caching von Proxys, die von ISPs verwendet werden, um die Belastung des Netzwerks zu verringern.)



2

AFAIK, der Browser (zumindest Firefox) fordert jede Ressource an, sobald sie analysiert wird. Wenn es auf ein img-Tag stößt, fordert es dieses Bild an, sobald das img-Tag analysiert wurde. Und das kann sein, noch bevor es die Gesamtheit des HTML-Dokuments erhalten hat ... das heißt, es könnte immer noch das HTML-Dokument herunterladen, wenn dies passiert.

Für Firefox gelten Browserwarteschlangen, je nachdem, wie sie in about: config festgelegt sind. Beispielsweise wird nicht versucht, mehr als 8 Dateien gleichzeitig vom selben Server herunterzuladen. Die zusätzlichen Anforderungen werden in die Warteschlange gestellt. Ich denke, es gibt Domain-Limits, Proxy-Limits und andere Dinge, die auf der Mozilla-Website dokumentiert sind und in about: config festgelegt werden können. Ich habe irgendwo gelesen, dass der IE keine solchen Grenzen hat.

Das jQuery ready-Ereignis wird ausgelöst, sobald das Haupt-HTML-Dokument vorliegt heruntergeladen und das DOM analysiert wurde. Das Ladeereignis wird dann ausgelöst, sobald alle verknüpften Ressourcen (CSS, Bilder usw.) heruntergeladen und analysiert wurden. Dies wird in der jQuery-Dokumentation deutlich gemacht.

Wenn Sie die Reihenfolge steuern möchten, in der alles geladen wird, ist JavaScript meiner Meinung nach der zuverlässigste Weg, dies zu tun.



1

Die gewählte Antwort scheint nicht für moderne Browser zu gelten, zumindest nicht für Firefox 52. Ich habe festgestellt, dass die Anforderungen zum Laden von Ressourcen wie CSS und Javascript ausgegeben werden, bevor der HTML-Parser beispielsweise das Element erreicht

<html>
  <head>
    <!-- prints the date before parsing and blocks HTMP parsering -->
    <script>
      console.log("start: " + (new Date()).toISOString());
      for(var i=0; i<1000000000; i++) {};
    </script>

    <script src="jquery.js" type="text/javascript"></script>
    <script src="abc.js" type="text/javascript"></script>
    <link rel="stylesheets" type="text/css" href="abc.css"></link>
    <style>h2{font-wight:bold;}</style>
    <script>
      $(document).ready(function(){
      $("#img").attr("src", "kkk.png");
     });
   </script>
 </head>
 <body>
   <img id="img" src="abc.jpg" style="width:400px;height:300px;"/>
   <script src="kkk.js" type="text/javascript"></script>
   </body>
</html>

Was ich fand, dass die Startzeit von Anfragen zum Laden von CSS- und Javascript-Ressourcen nicht blockiert wurde. Es sieht so aus, als hätte Firefox einen HTML-Scan und identifiziert wichtige Ressourcen (img-Ressource ist nicht enthalten), bevor mit dem Parsen des HTML begonnen wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.