JS-скрипты, неудачно расположенные в HTML-коде, могут значительно снизить скорость загрузки страницы. Разберемся, как повысить скорость загрузки в старых версиях браузеров и как правильно использовать async
и defer
, которые поддерживаются в новых версиях.
Это адаптированный перевод статьи Efficiently load JavaScript with defer and async из блога проекта flaviocopes. Повествование ведется от лица автора оригинала.
Расположение имеет значение
Стандартный способ встраивания скрипта в HTML-код страницы выглядит так:
<script src="script.js"></script>
Каждый раз, когда встретится такая или похожая строка, будет выполнен запрос на получение данных файла, а парсер продолжит свою работу после выполнения скрипта.
Классический подход к обучению HTML предполагает, что теги скрипта должны находиться в <head>
:
<html>
<head>
<title>Title</title>
<script src="script.js"></script>
</head>
<body>
...
</body>
</html>
Однако такой подход приводит к задержкам при загрузке страницы. Когда анализатор доходит до строки со скриптом, он на время останавливается для его извлечения и выполнения, и только после этого переходит к разбору<body>
.
Распространенное решение проблемы — перенос скрипта в нижнюю часть страницы, перед закрывающим тегом </body>
. В этом случае скрипт выполняется после того, как вся страница уже проанализирована до тега.
Это лучшее решение по ускорению загрузки страницы для старых браузеров, которые не поддерживают атрибуты async
и defer
. О последних поговорим отдельно.
async и defer
Прежде чем начать, стоит уточнить, что использование обоих атрибутов накладывает некоторые ограничения, а приведенное ниже руководство по времени загрузки — не исчерпывающее.
Синтаксически и async
и defer
— булевые атрибуты, которые используются следующим образом:
<script async src="script.js"></script>
<script defer src="script.js"></script>
Если в коде есть оба атрибута, async
имеет приоритет и выполняется в первую очередь в современных версиях браузеров. В старых версиях, напротив, приоритет будет отдан defer
.
Проверить совместимость атрибутов с разными версиями браузеров можно по этим таблицам: раз и два
Важно отметить, что оба атрибута стоит использовать только в верхней части страницы (в <head>
): перенос в <body>
делает их совершенно бесполезными.
Производительность
Если async
и defer
отсутствуют в <head>
Синтаксический анализатор прекращает работу до тех пор, пока скрипт не будет выполнен. Как только этот процесс завершится, анализ продолжится.
Читайте также: Как сохранять фокус на протяжении всего обучения: советы от Хекслета
Если async
и defer
отсутствуют в <body>
Парсинг выполняется без пауз: сразу по его завершению загружается и выполняется скрипт. Синтаксический анализ выполняется еще до загрузки скрипта, поэтому страница загружается быстрее, чем в предыдущем случае.
Если async
находится в <head>
Сценарий загружается асинхронно, а синтаксический анализатор приостанавливает работу на время его выполнения.
Если defer
находится в <head>
Скрипт извлекается асинхронно и выполняется только после завершения анализа HTML.
Парсинг проходит с той же скоростью, как если бы скрипт находился в конце тега body
, но в целом выполнение скрипта завершается намного раньше, поскольку он загружается параллельно с парсингом HTML. Таким образом этот вариант — наиболее выигрышный с точки зрения скорости загрузки страницы.
Блокировка синтаксического анализа
async
приостанавливает синтаксический анализ страницы, а defer
— нет.
Блокировка рендеринга
Ни async
, ни defer
не блокируют рендеринг — этот процесс полностью зависит от кода на странице. Поэтому важно убедиться, что сценарии запускаются после события onLoad
.
domInteractive
Скрипты defer
выполняются сразу после события domInteractive
. Последнее, в свою очередь, происходит после загрузки, анализа и построения DOM HTML.
СSS и изображения на этом этапе еще не проанализированы и не загружены: как только это произойдет, браузер сначала выдаст событие domComplete
, а затем — onLoad
.
Порядок выполнения
Еще один аргумент за использование defer
— скрипты, помеченные как async
, выполняются в случайном порядке, тогда как скрипты с defer
— в строго определенном.
Как ускорить загрузку страницы
Лучший способ — прописать скрипты в <head>
и добавить атрибут defer
в тег script
. Этот сценарий быстро запускает событие domInteractive
:
<script defer src="script.js"></script>
Никогда не останавливайтесь: В программировании говорят, что нужно постоянно учиться даже для того, чтобы просто находиться на месте. Развивайтесь с нами — на Хекслете есть сотни курсов по разработке на разных языках и технологиях