Вот что происходит, когда браузер загружает сайт с <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 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 src="path/to/script1.js" async></script>
<script src="path/to/script2.js" async></script>
Сценарии с атрибутом async выполняются асинхронно. Это означает, что скрипт выполняется сразу после его загрузки, не блокируя браузер.
Это означает, что сценарий 2 может быть загружен и выполнен до сценария 1.
Согласно http://caniuse.com/#feat=script-async , 97,78% всех браузеров поддерживают это.
Перенести
<script src="path/to/script1.js" defer></script>
<script src="path/to/script2.js" defer></script>
Сценарии с атрибутом defer выполняются по порядку (т. Е. Сначала сценарий 1, затем сценарий 2). Это также не блокирует браузер.
В отличие от асинхронных сценариев, отложенные сценарии выполняются только после полной загрузки документа.
Согласно http://caniuse.com/#feat=script-defer , 97,79% всех браузеров поддерживают это. 98,06% поддерживают это хотя бы частично.
Важное замечание о совместимости браузера: в некоторых случаях IE <= 9 может выполнять отложенные сценарии не по порядку. Если вам нужно поддерживать эти браузеры, пожалуйста, прочитайте это в первую очередь!
Вывод
Текущий уровень техники заключается в том, чтобы помещать сценарии в <head>
тег и использовать атрибуты async
or defer
. Это позволяет загружать ваши скрипты как можно быстрее, не блокируя ваш браузер.
Хорошо, что ваш сайт все равно должен корректно загружаться в 2% браузеров, которые не поддерживают эти атрибуты, в то время как другие 98% ускоряются.