Руководство: как увеличить скорость загрузки страницы со скриптами с помощью defer и async

JS-скрипты, неудачно расположенные в HTML-коде, могут значительно снизить скорость загрузки страницы. Разберемся, как повысить скорость загрузки в старых версиях браузеров и как правильно использовать async
и defer
, которые поддерживаются в новых версиях.
Это адаптированный перевод статьи Efficiently load JavaScript with defer and async из блога проекта flaviocopes. Повествование ведется от лица автора оригинала.
Содержание
Расположение имеет значение
Стандартный способ встраивания скрипта в HTML-код страницы выглядит так:
<script src="script.js"></script>
Каждый раз, когда встретится такая или похожая строка, будет выполнен запрос на получение данных файла, а парсер продолжит свою работу после выполнения скрипта.
Классический подход к обучению HTML предполагает, что теги скрипта должны находиться в <head>
:
Однако такой подход приводит к задержкам при загрузке страницы. Когда анализатор доходит до строки со скриптом, он на время останавливается для его извлечения и выполнения, и только после этого переходит к разбору<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>
Никогда не останавливайтесь:
В программировании говорят, что нужно постоянно учиться даже для того, чтобы просто находиться на месте. Развивайтесь с нами — на Хекслете есть сотни курсов по разработке на разных языках и технологиях
Oleg Sabitov
4 года назад