it-roy-ru.com

Загрузка и последовательность выполнения веб-страницы?

Я сделал несколько веб-проектов, но я не слишком много думаю о последовательности загрузки и выполнения обычной веб-страницы. Но теперь мне нужно знать детали. Трудно найти ответы от Google или SO, поэтому я создал этот вопрос.

Пример страницы выглядит так:

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

Итак, вот мои вопросы:

  1. Как загружается эта страница?
  2. Какова последовательность загрузки?
  3. Когда выполняется код JS? (встроенный и внешний)
  4. Когда выполняется CSS (применяется)?
  5. Когда исполняется $ (document) .ready?
  6. Будет ли загружен abc.jpg? Или это просто скачать kkk.png?

У меня есть следующее понимание:

  1. Браузер сначала загружает HTML (DOM).
  2. Браузер начинает загружать внешние ресурсы сверху вниз, строка за строкой.
  3. Если встречается <script>, загрузка будет заблокирована и дождется загрузки и выполнения файла JS, а затем продолжится.
  4. Другие ресурсы (CSS/изображения) загружаются параллельно и выполняются при необходимости (например, CSS).

Или это так:

Браузер анализирует HTML (DOM) и получает внешние ресурсы в виде массива или структуры, подобной стеку. После загрузки HTML браузер начинает загружать внешние ресурсы в структуре параллельно и выполнять до тех пор, пока не будут загружены все ресурсы. Затем DOM будет изменен в соответствии с поведением пользователя в зависимости от JS.

Может ли кто-нибудь дать подробное объяснение того, что происходит, когда вы получите ответ HTML-страницы? Отличается ли это в разных браузерах? Любая ссылка на этот вопрос?

Благодарю.

Правка:

Я провел эксперимент в Firefox с Firebug. И это показывает как следующее изображение: alt text

231
Zhu Tao

Согласно вашему образцу,

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

примерно поток выполнения выглядит следующим образом:

  1. Документ HTML загружается
  2. Начинается разбор HTML-документа
  3. Разбор HTML достигает <script src="jquery.js" ...
  4. jquery.js загружен и проанализирован
  5. Разбор HTML достигает <script src="abc.js" ...
  6. abc.js загружен, проанализирован и запущен
  7. Разбор HTML достигает <link href="abc.css" ...
  8. abc.css загружен и проанализирован
  9. Разбор HTML достигает <style>...</style>
  10. Внутренние правила CSS анализируются и определяются
  11. Разбор HTML достигает <script>...</script>
  12. Внутренний Javascript анализируется и запускается
  13. Разбор HTML достигает <img src="abc.jpg" ...
  14. abc.jpg загружается и отображается
  15. Разбор HTML достигает <script src="kkk.js" ...
  16. kkk.js загружен, проанализирован и запущен
  17. Разбор HTML-документа заканчивается

Обратите внимание, что загрузка может быть асинхронной и неблокируемой из-за поведения браузера. Например, в Firefox есть этот параметр, который ограничивает количество одновременных запросов на домен.

Также в зависимости от того, был ли компонент уже кэширован или нет, этот компонент может не быть запрошен снова в запросе ближайшего будущего. Если компонент был кэширован, компонент будет загружен из кэша вместо фактического URL.

Когда анализ завершен, а документ готов и загружен, запускаются события onload. Таким образом, когда запускается onload, запускается $("#img").attr("src","kkk.png");. Так:

  1. Документ готов, загрузка загружена.
  2. Javascript выполняет хиты $("#img").attr("src", "kkk.png");
  3. kkk.png загружается и загружается в #img

Событие $(document).ready() фактически является событием, которое запускается, когда все компоненты страницы загружены и готовы. Подробнее об этом читайте: http://docs.jquery.com/Tutorials:Introduction_$ (document) .ready ()

Редактировать - эта часть более подробно описывает параллельную или нет:

По умолчанию, и, насколько я понимаю, браузер обычно запускает каждую страницу тремя способами: анализатор HTML, Javascript/DOM и CSS. 

Синтаксический анализатор HTML отвечает за синтаксический анализ и интерпретацию языка разметки и, следовательно, должен иметь возможность вызывать другие 2 компонента. 

Например, когда парсер встречает эту строку:

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

Парсер сделает 3 вызова: два в Javascript и один в CSS. Во-первых, парсер создаст этот элемент и зарегистрирует его в пространстве имен DOM вместе со всеми атрибутами, связанными с этим элементом. Во-вторых, будет вызван синтаксический анализатор, чтобы связать событие onclick с этим конкретным элементом. Наконец, он сделает еще один вызов в потоке CSS, чтобы применить стиль CSS к этому конкретному элементу.

Исполнение сверху вниз и однопоточное. Javascript может выглядеть многопоточным, но факт в том, что Javascript является однопоточным. Вот почему при загрузке внешнего файла JavaScript разбор основной HTML-страницы приостанавливается. 

Однако файлы CSS можно загружать одновременно, потому что правила CSS всегда применяются, то есть элементы всегда перерисовываются с использованием самых свежих определенных правил CSS, что делает его разблокированным.

Элемент будет доступен в DOM только после его анализа. Таким образом, при работе с конкретным элементом сценарий всегда помещается после или внутри события onload окна.

Подобный скрипт вызовет ошибку (в jQuery):

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

Потому что, когда скрипт анализируется, элемент #mydiv все еще не определен. Вместо этого это будет работать:

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

OR

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

1) HTML загружен.

2) HTML анализируется постепенно. При получении запроса на актив браузер пытается загрузить ресурс. Конфигурация по умолчанию для большинства HTTP-серверов и большинства браузеров заключается в параллельной обработке только двух запросов. IE можно перенастроить для одновременной загрузки неограниченного количества ресурсов. Стив Соудерс смог загрузить более 100 запросов параллельно в IE. Исключением является то, что запросы скриптов блокируют параллельные запросы ресурсов в IE. Вот почему настоятельно рекомендуется поместить весь JavaScript во внешние файлы JavaScript и поместить запрос непосредственно перед закрывающим тегом body в HTML.

3) После разбора HTML DOM отображается. CSS отображается параллельно с отображением DOM практически во всех пользовательских агентах. В результате настоятельно рекомендуется поместить весь код CSS во внешние файлы CSS, которые запрашиваются как можно выше в разделе <head> </ head> документа. В противном случае страница обрабатывается до появления позиции запроса CSS в DOM, а затем рендеринг начинается сверху.

4) Только после полной визуализации DOM и разрешения всех ресурсов на странице либо по истечении времени ожидания JavaScript выполняется из события onload. IE7, и я не уверен насчет IE8, быстро не активирует ресурсы, если на запрос ресурса не получен HTTP-ответ. Это означает, что актив, запрашиваемый JavaScript, встроенным в страницу, то есть JavaScript, записанный в теги HTML, который не содержится в функции, может на несколько часов препятствовать выполнению события onload. Эта проблема может быть вызвана, если такой встроенный код существует на странице и не выполняется из-за столкновения пространства имен, которое вызывает сбой кода.

Из вышеперечисленных шагов наиболее ресурсоемким является анализ DOM/CSS. Если вы хотите, чтобы ваша страница обрабатывалась быстрее, напишите эффективный CSS, исключив избыточные инструкции и объединив инструкции CSS в наименьшее количество ссылок на элементы. Сокращение количества узлов в вашем DOM-дереве также приведет к более быстрому рендерингу.

Имейте в виду, что каждый ресурс, который вы запрашиваете из вашего HTML или даже из ваших ресурсов CSS/JavaScript, запрашивается с отдельным заголовком HTTP. Это потребляет пропускную способность и требует обработки для каждого запроса. Если вы хотите, чтобы ваша страница загружалась как можно быстрее, уменьшите количество HTTP-запросов и уменьшите размер вашего HTML. Вы не оказываете никакой помощи пользователю, усредняя вес страницы в 180 Кб только из HTML. Многие разработчики соглашаются с ошибкой, заключающейся в том, что пользователь принимает решение о качестве контента на странице за 6 наносекунд, а затем удаляет DNS-запрос со своего сервера и записывает свой компьютер, если он недоволен, поэтому вместо этого они предоставляют самую красивую страницу на 250 тыс. HTML. Сделайте ваш HTML коротким и приятным, чтобы пользователь мог быстрее загружать ваши страницы. Ничто не улучшает пользовательский опыт, как быстрая и отзывчивая веб-страница.

33
austin cheney

Откройте свою страницу в Firefox и получите аддон HTTPFox. Он скажет вам все, что вам нужно.

Нашел это в архиве.incuito:

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

Когда вы впервые запрашиваете страницу, ваш браузер отправляет запрос GET на сервер, который возвращает HTML к браузер. Затем браузер запускается парсинг страницы (возможно, до того, как все из этого было возвращено).

Когда он находит ссылку на внешняя сущность, такая как файл CSS, файл изображения, файл сценария, Flash файл или что-то еще, внешнее по отношению к страница (либо на том же сервере /домен или нет), он готовится к сделать еще один запрос GET для этого ресурс.

Однако стандарт HTTP указывает что браузер не должен делать больше чем два одновременных запроса к тот же домен. Так что ставит каждый запрос к определенному домену в очереди, и когда каждая сущность возвращается, она начинается следующий в очереди за этим домен.

Время, которое требуется для объекта возвращается зависит от его размера, загрузить сервер в данный момент опыт и активность каждая машина между машина работает с браузером и сервер. Список этих машин в принципе может отличаться для каждый запрос, в той степени, что один изображение может путешествовать из США ко мне в Великобритании над Атлантикой, пока другой с того же сервера выходит через Тихий океан, Азию и Европу что занимает больше времени. Таким образом, вы можете получить последовательность, подобная следующей, где страница содержит (в этом порядке) ссылки до трех файлов сценария и пяти изображений файлы разных размеров:

  1. ПОЛУЧИТЬ script1 и script2; запрос очереди для script3 и images1-5.
  2. script2 прибывает (это меньше, чем script1): GET script3, очередь images1-5.
  3. script1 прибывает; ПОЛУЧИТЬ image1, очередь изображений2-5.
  4. image1 прибывает, ПОЛУЧИТЕ image2, очередь images3-5.
  5. script3 не может прибыть из-за проблем с сетью - GET script3 снова (автоматическая повторная попытка).
  6. image2 прибывает, script3 все еще не здесь; ПОЛУЧИТЬ image3, очередь изображений4-5.
  7. изображение 3 прибывает; ПОЛУЧИТЬ image4, очередь image5, script3 еще в пути.
  8. image4 прибывает, ПОЛУЧИТЕ image5;
  9. изображение5 прибывает.
  10. script3 прибывает.

Короче говоря: любой старый порядок, в зависимости от что делает сервер, что остальная часть интернета занимается, а есть ли ошибки в чем-либо и должен быть восстановлен. Это может кажется странным способом сделать вещи, но это было бы буквально Интернет невозможно (не просто WWW) работать с любой степенью надежности, если это не было сделано путь.

Кроме того, внутренняя очередь браузера может не получить объекты в порядке они появляются на странице - это не требуется по любому стандарту.

(О, и не забудьте о кэшировании как в Браузере, так и в прокси-серверах кэширования Используемых интернет-провайдерами для облегчения загрузки сети )

12
tahdhaze09

Если вы спрашиваете об этом, потому что хотите ускорить свой веб-сайт, проверьте страницу Yahoo на Лучшие практики для ускорения вашего веб-сайта . У этого есть много лучших методов для ускорения Вашего веб-сайта.

6
a paid nerd

Dynatrace AJAX Edition показывает точную последовательность загрузки, анализа и выполнения страницы.

1
Chetan Sastry

AFAIK, браузер (по крайней мере, Firefox) запрашивает каждый ресурс, как только он его анализирует. Если он встречает тег img, он запросит это изображение, как только тег img будет проанализирован. И это может произойти даже до того, как он получит весь документ HTML ... то есть он все еще может загружать документ HTML, когда это произойдет.

Для Firefox существуют очереди браузера, которые применяются в зависимости от того, как они установлены в about: config. Например, он не будет пытаться загрузить более 8 файлов одновременно с одного сервера ... дополнительные запросы будут поставлены в очередь. Я думаю, что есть ограничения для каждого домена, для каждого прокси и другие вещи, которые описаны на веб-сайте Mozilla и могут быть установлены в about: config. Я где-то читал, что IE не имеет таких ограничений.

Событие готовности jQuery вызывается, как только основной HTML-документ был загружен и проанализирован DOM. Затем событие загрузки запускается после загрузки и анализа всех связанных ресурсов (CSS, изображений и т.д.). Это ясно показано в документации по jQuery.

Если вы хотите контролировать порядок загрузки всего этого, я считаю, что наиболее надежный способ сделать это - использовать JavaScript.

1
Rolf

Выбранный ответ, похоже, не относится к современным браузерам, по крайней мере, в Firefox 52. Я заметил, что запросы на загрузку ресурсов, таких как css, javascript, выдаются до того, как анализатор HTML достигает элемента, например

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

Что я обнаружил, что время начала запросов на загрузку ресурсов CSS и JavaScript не были заблокированы. Похоже, что Firefox имеет сканирование HTML и идентифицирует ключевые ресурсы (ресурс img не включен) перед началом анализа HTML.

0
Xiaoming