Séquence de chargement et d'exécution d'une page Web?

244

J'ai fait quelques projets basés sur le Web, mais je ne pense pas trop à la séquence de chargement et d'exécution d'une page Web ordinaire. Mais maintenant, j'ai besoin de connaître les détails. Il est difficile de trouver des réponses de Google ou SO, j'ai donc créé cette question.

Un exemple de page est comme ceci:

<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>

Donc, voici mes questions:

  1. Comment se charge cette page?
  2. Quelle est la séquence du chargement?
  3. Quand le code JS est-il exécuté? (en ligne et externe)
  4. Quand le CSS est-il exécuté (appliqué)?
  5. Quand $ (document) est-il déjà exécuté?
  6. Abc.jpg sera-t-il téléchargé? Ou s'agit-il simplement de télécharger kkk.png?

J'ai la compréhension suivante:

  1. Le navigateur charge le html (DOM) dans un premier temps.
  2. Le navigateur commence à charger les ressources externes de haut en bas, ligne par ligne.
  3. Si a <script>est rencontré, le chargement sera bloqué et attendra que le fichier JS soit chargé et exécuté, puis continuez.
  4. D'autres ressources (CSS / images) sont chargées en parallèle et exécutées si nécessaire (comme CSS).

Ou est-ce comme ça:

Le navigateur analyse le html (DOM) et obtient les ressources externes dans un tableau ou une structure de type pile. Une fois le html chargé, le navigateur commence à charger les ressources externes dans la structure en parallèle et à exécuter, jusqu'à ce que toutes les ressources soient chargées. Ensuite, le DOM sera modifié en fonction des comportements de l'utilisateur en fonction du JS.

Quelqu'un peut-il donner une explication détaillée de ce qui se passe lorsque vous avez la réponse d'une page html? Cela varie-t-il dans différents navigateurs? Une référence à cette question?

Merci.

ÉDITER:

J'ai fait une expérience dans Firefox avec Firebug. Et cela apparaît comme l'image suivante: texte alternatif

Zhu Tao
la source
11
Steve Souders a fait beaucoup de travail dans ce domaine. Google pour steve + souders + haute + performance et jetez un œil.
anddoutoi
3
Je ne parle pas de l'optimisation des performances. Je veux connaître le détail.
Zhu Tao
2
En lisant son travail, ma compréhension de la façon dont "ça" fonctionne en détail a décuplé, donc c'est toujours un commentaire valable. Le droit d'auteur ne me permet pas de citer l'intégralité de son livre ici, je vous suggère donc de consulter son travail.
anddoutoi
3
Une bonne description de l'ordre dans
lequel les

Réponses:

277

Selon votre échantillon,

<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>

à peu près le flux d'exécution est le suivant:

  1. Le document HTML est téléchargé
  2. L'analyse du document HTML démarre
  3. L'analyse HTML atteint <script src="jquery.js" ...
  4. jquery.js est téléchargé et analysé
  5. L'analyse HTML atteint <script src="abc.js" ...
  6. abc.js est téléchargé, analysé et exécuté
  7. L'analyse HTML atteint <link href="abc.css" ...
  8. abc.css est téléchargé et analysé
  9. L'analyse HTML atteint <style>...</style>
  10. Les règles CSS internes sont analysées et définies
  11. L'analyse HTML atteint <script>...</script>
  12. Javascript interne est analysé et exécuté
  13. L'analyse HTML atteint <img src="abc.jpg" ...
  14. abc.jpg est téléchargé et affiché
  15. L'analyse HTML atteint <script src="kkk.js" ...
  16. kkk.js est téléchargé, analysé et exécuté
  17. L'analyse du document HTML se termine

Notez que le téléchargement peut être asynchrone et non bloquant en raison des comportements du navigateur. Par exemple, dans Firefox, ce paramètre limite le nombre de demandes simultanées par domaine.

En outre, selon que le composant a déjà été mis en cache ou non, le composant peut ne pas être demandé à nouveau dans une demande proche. Si le composant a été mis en cache, le composant sera chargé à partir du cache au lieu de l'URL réelle.

Une fois l'analyse terminée et le document prêt et chargé, les événements onloadsont déclenchés. Ainsi, lorsque onloadest tiré, le $("#img").attr("src","kkk.png");est exécuté. Alors:

  1. Le document est prêt, la charge est déclenchée.
  2. Résultats d'exécution Javascript $("#img").attr("src", "kkk.png");
  3. kkk.png est téléchargé et chargé dans #img

L' $(document).ready()événement est en fait l'événement déclenché lorsque tous les composants de la page sont chargés et prêts. En savoir plus à ce sujet: http://docs.jquery.com/Tutorials:Introducing_$ (document) .ready ()

Edit - Cette partie développe plus sur la partie parallèle ou non:

Par défaut, et d'après ma compréhension actuelle, le navigateur exécute généralement chaque page de 3 manières: analyseur HTML, Javascript / DOM et CSS.

L'analyseur HTML est chargé d'analyser et d'interpréter le langage de balisage et doit donc être en mesure d'appeler les 2 autres composants.

Par exemple, lorsque l'analyseur rencontre cette ligne:

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

L'analyseur effectuera 3 appels, deux vers Javascript et un vers CSS. Premièrement, l'analyseur va créer cet élément et l'enregistrer dans l'espace de noms DOM, avec tous les attributs liés à cet élément. Deuxièmement, l'analyseur appellera pour lier l'événement onclick à cet élément particulier. Enfin, il fera un autre appel au thread CSS pour appliquer le style CSS à cet élément particulier.

L'exécution est descendante et monothread. Javascript peut sembler multithread, mais le fait est que Javascript est monothread. C'est pourquoi lors du chargement d'un fichier javascript externe, l'analyse de la page HTML principale est suspendue.

Cependant, les fichiers CSS peuvent être téléchargés simultanément car les règles CSS sont toujours appliquées - c'est-à-dire que les éléments sont toujours repeints avec les règles CSS les plus récentes définies - le rendant ainsi déblocable.

Un élément ne sera disponible dans le DOM qu'après avoir été analysé. Ainsi, lorsque vous travaillez avec un élément spécifique, le script est toujours placé après ou dans l'événement onload de la fenêtre.

Un script comme celui-ci provoquera une erreur (sur jQuery):

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

Parce que lorsque le script est analysé, l' #mydivélément n'est toujours pas défini. Au lieu de cela, cela fonctionnerait:

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

OU

<script type="text/javascript">/* <![CDATA[ */
  $(window).ready(function(){
                    alert($("#mydiv").html());
                  });
/* ]]> */</script>
<div id="mydiv">Hello World</div>
mauris
la source
4
Merci. Mais vous avez mentionné que le téléchargement peut être asynchrone et non bloquant en raison des comportements du navigateur , alors quel type de composants peut être téléchargé en asyn (prenez FF comme exemple)? <script>va bloquer d'autres composants, non? Une référence sur la spécification à chaque navigateur?
Zhu Tao,
4
$ (document) .ready () est déclenché lorsque le DOM est terminé, pas lorsque tous les composants de la page sont chargés
Pierre
2
@Pierre par composants de page, je voulais dire le DOM -> quels que soient les composants du DOM.
mauris
3
juste pour clarifier ... le window.onload normal se produit après # 17 ... donc à quel # code de jquery $ (document) .ready () s'exécute-t-il? # 12? mais le DOM lui-même est chargé au n ° 1 à droite?
armyofda12mnkeys
1
Si dans l'onglet <body>, si nous ajoutons un <link href = "bootstrap.min.css" rel = "stylesheet" /> entre les balises <img> et <script>, img ne s'affiche pas jusqu'à ce que le bootstrap soit téléchargé ... donc je pense que l'étape [13], [14] doit être modifiée ... quelqu'un peut-il expliquer ce comportement?
Bhuvan
34

1) Le HTML est téléchargé.

2) Le HTML est analysé progressivement. Lorsqu'une demande d'actif est atteinte, le navigateur tente de télécharger l'actif. Une configuration par défaut pour la plupart des serveurs HTTP et la plupart des navigateurs consiste à ne traiter que deux demandes en parallèle. IE peut être reconfiguré pour télécharger un nombre illimité de ressources en parallèle. Steve Souders a pu télécharger plus de 100 requêtes en parallèle sur IE. L'exception est que les requêtes de script bloquent les requêtes d'actifs parallèles dans IE. C'est pourquoi il est fortement suggéré de mettre tout le JavaScript dans des fichiers JavaScript externes et de placer la demande juste avant la balise de fermeture du corps dans le HTML.

3) Une fois le HTML analysé, le DOM est rendu. CSS est rendu parallèlement au rendu du DOM dans presque tous les agents utilisateurs. Par conséquent, il est fortement recommandé de placer tout le code CSS dans des fichiers CSS externes qui sont demandés aussi haut que possible dans la section <head> </head> du document. Sinon, la page est rendue jusqu'à l'occurrence de la position de la demande CSS dans le DOM, puis le rendu recommence à partir du haut.

4) Ce n'est qu'après le rendu complet du DOM et que les demandes pour tous les actifs de la page sont résolues ou que le délai d'expiration est exécuté par JavaScript à partir de l'événement onload. IE7, et je ne suis pas sûr d'IE8, n'expire pas rapidement les actifs si aucune réponse HTTP n'est reçue de la demande d'actifs. Cela signifie qu'un actif demandé par JavaScript en ligne sur la page, c'est-à-dire JavaScript écrit dans des balises HTML qui n'est pas contenu dans une fonction, peut empêcher l'exécution de l'événement onload pendant des heures. Ce problème peut être déclenché si un tel code en ligne existe dans la page et ne parvient pas à s'exécuter en raison d'une collision d'espace de noms qui provoque un crash de code.

Parmi les étapes ci-dessus, celle qui consomme le plus de CPU est l'analyse du DOM / CSS. Si vous souhaitez que votre page soit traitée plus rapidement, écrivez du CSS efficace en éliminant les instructions redondantes et en consolidant les instructions CSS dans le moins de références d'éléments possibles. La réduction du nombre de nœuds dans votre arborescence DOM produira également un rendu plus rapide.

Gardez à l'esprit que chaque actif que vous demandez à partir de votre HTML ou même de vos actifs CSS / JavaScript est demandé avec un en-tête HTTP distinct. Cela consomme de la bande passante et nécessite un traitement par demande. Si vous souhaitez accélérer le chargement de votre page, réduisez le nombre de requêtes HTTP et réduisez la taille de votre code HTML. Vous ne faites aucune faveur à votre utilisateur en faisant la moyenne du poids de la page à 180k à partir du HTML seul. De nombreux développeurs souscrivent à une erreur selon laquelle un utilisateur se décide sur la qualité du contenu de la page en 6 nanosecondes, puis purge la requête DNS de son serveur et brûle son ordinateur s'il est mécontent.Au lieu de cela, ils fournissent la plus belle page possible sur 250k de HTML. Gardez votre HTML court et doux afin qu'un utilisateur puisse charger vos pages plus rapidement.


la source
2
consolider les instructions CSS dans le moins de références d'éléments possibles Cela semble étrange. Si je dois styliser trois éléments, je dois référencer exactement trois éléments. Je ne peux pas faire référence à un style dix, n'est-ce pas? Ou développez-le
Green
12

Ouvrez votre page dans Firefox et obtenez l'addon HTTPFox. Il vous dira tout ce dont vous avez besoin.

J'ai trouvé ceci sur archivist.incuito:

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

Lorsque vous demandez une page pour la première fois, votre navigateur envoie une demande GET au serveur, qui renvoie le code HTML au navigateur. Le navigateur commence alors l'analyse de la page (peut-être avant que tout ne soit retourné).

Lorsqu'il trouve une référence à une entité externe telle qu'un fichier CSS, un fichier image, un fichier script, un fichier Flash ou tout autre élément externe à la page (soit sur le même serveur / domaine ou non), il se prépare à faire une autre demande GET pour cette ressource.

Cependant, la norme HTTP spécifie que le navigateur ne doit pas effectuer plus de deux demandes simultanées vers le même domaine. Ainsi, il place chaque demande dans un domaine particulier dans une file d'attente, et lorsque chaque entité est renvoyée, il démarre la suivante dans la file d'attente pour ce domaine.

Le temps nécessaire pour qu'une entité soit renvoyée dépend de sa taille, de la charge que le serveur subit actuellement et de l'activité de chaque machine entre la machine exécutant le navigateur et le serveur. La liste de ces machines peut en principe être différente pour chaque demande, dans la mesure où une image peut voyager des États-Unis à moi au Royaume-Uni au-dessus de l'Atlantique, tandis qu'une autre provenant du même serveur sort via le Pacifique, l'Asie et l'Europe, ce qui prend plus de temps. Vous pouvez donc obtenir une séquence comme celle-ci, où une page a (dans cet ordre) des références à trois fichiers de script et cinq fichiers image, tous de tailles différentes:

  1. GET script1 et script2; demande de file d'attente pour script3 et images1-5.
  2. script2 arrive (il est plus petit que script1): GET script3, files images1-5.
  3. script1 arrive; GET image1, files d'attente images2-5.
  4. image1 arrive, GET image2, file d'attente images3-5.
  5. script3 n'arrive pas en raison d'un problème de réseau - OBTENEZ à nouveau script3 (nouvelle tentative automatique).
  6. image2 arrive, script3 n'est toujours pas là; GET image3, files d'attente images4-5.
  7. l'image 3 arrive; GET image4, file d'attente image5, script3 toujours en cours.
  8. image4 arrive, GET image5;
  9. image5 arrive.
  10. script3 arrive.

En bref: tout ordre ancien, en fonction de ce que fait le serveur, de ce que fait le reste d'Internet, et si quelque chose a des erreurs et doit être récupéré. Cela peut sembler une façon étrange de faire les choses, mais il serait littéralement impossible pour Internet (pas seulement le WWW) de fonctionner avec un certain degré de fiabilité s'il n'était pas fait de cette façon.

De plus, il est possible que la file d'attente interne du navigateur ne récupère pas les entités dans l'ordre dans lequel elles apparaissent dans la page - ce n'est pas requis par aucune norme.

(Oh, et n'oubliez pas la mise en cache, à la fois dans le navigateur et dans les procurations de mise en cache utilisées par les FAI pour alléger la charge sur le réseau.)

tahdhaze09
la source
6

Si vous posez cette question parce que vous voulez accélérer votre site Web, consultez la page de Yahoo sur les meilleures pratiques pour accélérer votre site Web . Il contient de nombreuses bonnes pratiques pour accélérer votre site Web.

un nerd payé
la source
2

AFAIK, le navigateur (au moins Firefox) demande toutes les ressources dès qu'il les analyse. S'il rencontre une balise img, il demandera cette image dès que la balise img aura été analysée. Et cela peut être même avant qu'il n'ait reçu la totalité du document HTML ... c'est-à-dire qu'il pourrait toujours télécharger le document HTML lorsque cela se produit.

Pour Firefox, il existe des files d'attente de navigateur qui s'appliquent, selon la façon dont elles sont définies dans about: config. Par exemple, il ne tentera pas de télécharger plus de 8 fichiers à la fois à partir du même serveur ... les demandes supplémentaires seront mises en file d'attente. Je pense qu'il existe des limites par domaine, par limite de proxy et d'autres choses, qui sont documentées sur le site Web de Mozilla et peuvent être définies dans about: config. J'ai lu quelque part qu'IE n'a pas de telles limites.

L'événement jQuery ready est déclenché dès que le document HTML principal a été téléchargé et qu'il est analysé par DOM. Ensuite, l'événement de chargement est déclenché une fois que toutes les ressources liées (CSS, images, etc.) ont également été téléchargées et analysées. Il est précisé dans la documentation jQuery.

Si vous voulez contrôler l'ordre dans lequel tout ce qui est chargé, je pense que le moyen le plus fiable de le faire est via JavaScript.

Rolf
la source
1

Dynatrace AJAX Edition vous montre la séquence exacte de chargement, d'analyse et d'exécution des pages.

Chetan S
la source
1

La réponse choisie ne s'applique pas aux navigateurs modernes, du moins sur Firefox 52. Ce que j'ai observé, c'est que les demandes de chargement de ressources comme css, javascript sont émises avant que l'analyseur HTML n'atteigne l'élément, par exemple

<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>

Ce que j'ai trouvé que l'heure de début des demandes de chargement des ressources css et javascript n'était pas bloquée. On dirait que Firefox a un scan HTML et identifie les ressources clés (la ressource img n'est pas incluse) avant de commencer à analyser le HTML.

Xiaoming
la source