Вот что происходит, когда браузер загружает веб-сайт с тегом <script>
:
- Получить страницу HTML (например, index.html)
- Начать разбор HTML
- Синтаксический анализатор обнаружил тег
<script>
, ссылающийся на внешний файл сценария.
- Браузер запрашивает файл скрипта. Тем временем парсер блокирует и прекращает анализ другого HTML-кода на вашей странице.
- Через некоторое время скрипт загружается и впоследствии выполняется.
- Анализатор продолжает синтаксический анализ остальной части HTML-документа.
Шаг # 4 вызывает плохой пользовательский опыт. Ваш веб-сайт в основном перестает загружаться, пока вы не загрузите все скрипты. Если есть одна вещь, которую пользователи ненавидят, это ждет загрузки веб-сайта.
Почему это вообще происходит?
Любой скрипт может вставить свой собственный HTML с помощью document.write()
или других манипуляций с DOM. Это подразумевает, что синтаксический анализатор должен ждать, пока скрипт не будет загружен и выполнен, прежде чем он сможет безопасно проанализировать остальную часть документа. В конце концов, скрипт мог бы вставить свой собственный HTML в документ.
Однако большинство разработчиков JavaScript больше не манипулируют DOM , пока документ загружается. Вместо этого они ждут, пока документ не будет загружен, прежде чем изменять его. Например:
<!-- index.html -->
<html>
<head>
<title>My Page</title>
<script type="text/javascript" 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";
});
Поскольку ваш браузер не знает, что my-script.js не будет изменять документ, пока он не будет загружен и выполнен, синтаксический анализатор прекращает синтаксический анализ.
Устаревшая рекомендация
Старый подход к решению этой проблемы заключался в размещении тегов <script>
внизу вашего <body>
, поскольку это гарантирует, что анализатор не будет заблокирован до самого конца.
У этого подхода есть своя проблема: браузер не может начать загрузку сценариев, пока весь документ не будет проанализирован. Для больших веб-сайтов с большими сценариями и таблицами стилей возможность загрузки сценария как можно скорее очень важна для производительности. Если ваш сайт не загружается в течение 2 секунд, люди переходят на другой сайт.
В оптимальном решении браузер начнет загрузку ваших сценариев как можно скорее, в то же время анализируя остальную часть вашего документа.
Современный подход
Сегодня браузеры поддерживают атрибуты async
и defer
в скриптах. Эти атрибуты сообщают браузеру, что безопасно продолжать анализ во время загрузки сценариев.
асинхронный
<script type="text/javascript" src="path/to/script1.js" async></script>
<script type="text/javascript" src="path/to/script2.js" async></script>
Сценарии с асинхронным атрибутом выполняются асинхронно. Это означает, что скрипт выполняется сразу после загрузки, без блокировки браузера.
Это означает, что сценарий 2 можно загрузить и выполнить до сценария 1.
Согласно http://caniuse.com/#feat=script-async, 94,57% всех браузеров поддерживают это.
Перенести
<script type="text/javascript" src="path/to/script1.js" defer></script>
<script type="text/javascript" src="path/to/script2.js" defer></script>
Сценарии с атрибутом defer выполняются по порядку (то есть сначала сценарий 1, затем сценарий 2). Это также не блокирует браузер.
В отличие от асинхронных сценариев, отложенные сценарии выполняются только после загрузки всего документа.
Согласно http://caniuse.com/#feat=script-defer, 94,59% всех браузеров поддерживают это. 94,92% поддерживают его хотя бы частично.
Важное замечание о совместимости браузера: в некоторых случаях IE <= 9 может выполнять отложенные сценарии не по порядку. Если вам требуется поддержка этих браузеров, сначала прочтите <a href="https://github.com/h5bp/lazyweb-requests/issues/42" rel="noreferrer"> this !
Заключение
Современным уровнем техники является помещение сценариев в тег <head>
и использование атрибутов async
или defer
. Это позволяет загружать ваши скрипты как можно быстрее, не блокируя ваш браузер.
Хорошо, что ваш веб-сайт должен по-прежнему корректно загружаться в 6% браузеров, которые не поддерживают эти атрибуты, а другие 94% ускоряются.