Асинхронная и отложенная загрузка JavaScript на сайте
Приветствую, друзья! Знаете ли вы, что загрузка JavaScript является одним из самых узких мест в производительности сайта? Сегодня моя основная задача — объяснить что такое асинхронная загрузка скрипта и каким образом она влияет на быстродействие и производительность сайта.
Браузер, загружающий тег <script>
, останавливает рендеринг страницы до тех пор, пока не загрузится и не исполнится скрипт. Страница заблокирована и браузер пару секунд не отвечает на действия пользователя. Время задержки зависит от нескольких факторов:
- конфигурации хостинга,
- скорости интернет-соединения,
- размера файла и других…
По этой причине анализатор скорости загрузки сайта PageSpeed Insights рекомендует удалить из верхней части страницы код JavaScript, блокирующий её отображение. Хорошей практикой является размещение скриптов в нижней части сайта, например, перед закрывающим тегом </body>
или настройка асинхронной загрузки.
JS может изменить содержимое сайта и даже перенаправить на другой URL-адрес. В таком случае подключение скрипта в конце документа приведёт к эффекту «подергивания» страницы, подгружая новые или изменяя существующие элементы в верхней части.
Применение атрибутов async и defer для тега script
Давайте разберёмся, что из себя представляет асинхронная и отложенная работа JavaScript и какая принципиальная разница между атрибутами async
и defer
. Но вначале рассмотрим последовательность обработки документа при обычном подключении тега <script>
.
<script src="example.js"></script>
В наглядном примере я буду использовать следующие условные обозначения:
— обработка страницы | |
— загрузка скрипта | |
— выполнение скрипта |
Таким образом, последовательность обработки документа происходит по следующей схеме:
Разбор HTML-кода прерывается на время загрузки и выполнения скрипта, после чего продолжается. Отображение веб-страницы происходит с задержкой.
Атрибут defer
Атрибут defer
позволяет браузеру начать загрузку js-файлов параллельно, не останавливая дальнейшую обработку страницы. Их выполнение происходит после полного разбора объектной модели документа (от англ. Document Object Model, сокращенно DOM), при этом браузер гарантирует последовательность на основе порядка подключения файлов.
<script defer src="example.js"></script>
Схема последовательности обработки:
Это отложенная загрузка. Данный атрибут рекомендуется применять при подключении нескольких JS файлов, при условии что один скрипт зависит от другого и вам важна последовательность их выполнения.
Атрибут async
Поддержка атрибута async
появилась в HTML5, он разрешает браузеру загружать js-файлы параллельно и выполнять сразу после загрузки, не дожидаясь обработки остальной части страницы.
<script async src="example.js"></script>
Схема последовательности обработки:
Это асинхронная загрузка. Атрибут рекомендуется применять для таких скриптов, которые не оказывают значительного влияния на отображение документа. К ним относятся счётчики сбора статистики (Google Analytics, Яндекс Метрика), коды рекламных сетей (Рекламная сеть Яндекса, Google AdSense), кнопки социальных сетей и так далее.
Асинхронное подключение JavaScript снижает время загрузки страниц за счёт отсутствия задержки. Наряду с этим я рекомендую сжимать и объединять js-файлы в один, например, с помощью библиотеки Minify. Пользователям нравятся быстрые сайты 😎
Я у себя все скрипты отпустил вниз перед закрывающим тегом и в добавок половину скриптов перевел на асинхронную загрузку. Скорость выросла в разы, правда я делал эту оптимизацию давно.
С недавнего времени заметил что кнопки поделиться от яндекса немного тормозят загрузку, нужно наверное искать альтернативу или собирать самому. Денис, а ты как реализовал кнопки поделиться у себя?
Кстати про атрибут
defer
не знал, спасибо за инфу.Ответить
Сергей, кнопки Яндекса с относительно недавних пор подгружают скрипты Метрики. Директ тоже свою Метрику загружает, вот и начинает все жутко тормозить. Сторонние скрипты собирают свои данные и потом продают их рекламодателям, даже Share42, кажется, стал этим грешить… Поэтому использую другое решение, вскоре напишу об этом.
Ответить
Вот за это огромное спасибо! Буду внедрять в свой блог 😎
Ответить
Webliberty, хорошо с интересом почитаю.
Я нашел уже одно решение с кнопками, даже на одном проекте уже реализовал, с индивидуальным дизайном, все отлично работает но без счетчиков. Надо себе на сайт прикрутить будет. Правда хочется реализовать со счетчиком. Счетчики как бы информируют какой материал нравится читателю.
Ответить
При анализе сайта часто вижу подобную проблему. Торможение ресурса из-за кодов в верхней части. Но не мог понять в чем именно. Сегодня ознакомился с детальной информацией, поэтому сразу последуют меры.
Ответить
Спасибо, очень помогли. В PageSpeed Insights результат сразу взлетел. Сначала пробовал async, но у меня именно нужно было чтобы JQuery грузился раньше. Defer решил проблему. Еще раз спасибо 😀
Ответить
Подскажите как лучше оптимизировать два скрипта, которые больше всего едят процессорное время: Yandex Metrica и Jivochat?
Особенно критично при мобильной версии, у Метрики задержка 2173 ms!!! 😳
Ответить
Алексей, внешними скриптами сложно управлять, ведь они размещены на другом сервере, доступа к которому нет. Быть может пора задуматься о смене хостинга, если он не справляется? Или справляется, но хочется получить хорошие результаты в Google PageSpeed Insights? 🙂
Код счётчика Метрики можно вынести в отдельный файл и сохранить на своём сервере, тогда у вас появится возможность сжимать и кэшировать скрипт, но при любых изменениях со стороны Яндекса ваш локальный файл окажется неактуальным, перестанет собирать статистику или появятся сбои в его работе. На свой страх и риск. Здесь размещена инструкция как реализовать на практике.
Про Jivochat ничего толкового не скажу, так как не пользовался, если скрипт размещается на вашем сервере, то только сжимать и кэшировать, не забывая про асинхронную загрузку. Дополнительно посмотрите в сторону Preload, Prefetch и Preconnect для предварительной загрузки данных.
Ответить
Здравствуйте! Хостинг справляется, просто хочется получить хороший результат в Google PageSpeed Insights 🙂
Так чтобы Вы сделали? Или Ваша основная рекомендация — ничего не трогать — пусть работает как есть?
Ответить
Алексей, я рекомендую сделать всё что в ваших силах, а не оставлять как есть.
Для Метрики у меня в секции
<head>
заголовка сайта прописаны правила DNS Prefetch, что позволяет браузеру заранее обратиться к внешнему сайту для снижения задержки и увеличения производительности страницы:<link rel='dns-prefetch' href='https://mc.yandex.ru' />
Выше в примере приведён только один URL, хотя на самом деле Метрика загружает несколько ресурсов с разных адресов — все можно прописать. Экспериментируйте!
Ответить