Асинхронная и отложенная загрузка JavaScript на сайте

Приветствую, друзья! Знаете ли вы, что загрузка JavaScript является одним из самых узких мест в производительности сайта? Сегодня моя основная задача — объяснить что такое асинхронная загрузка скрипта и каким образом она влияет на быстродействие и производительность сайта.

Асинхронная загрузка JavaScript

Браузер, загружающий тег <script>, останавливает рендеринг страницы до тех пор, пока не загрузится и не исполнится скрипт. Страница заблокирована и браузер пару секунд не отвечает на действия пользователя. Время задержки зависит от нескольких факторов:

  • конфигурации хостинга,
  • скорости интернет-соединения,
  • размера файла и других…

По этой причине анализатор скорости загрузки сайта PageSpeed Insights рекомендует удалить из верхней части страницы код JavaScript, блокирующий её отображение. Хорошей практикой является размещение скриптов в нижней части сайта, например, перед закрывающим тегом </body> или настройка асинхронной загрузки.

Если код скрипта влияет на отображение верхней части сайта — не выносите его в отдельный файл, а встраивайте непосредственно в HTML.

JS может изменить содержимое сайта и даже перенаправить на другой URL-адрес. В таком случае подключение скрипта в конце документа приведёт к эффекту «подергивания» страницы, подгружая новые или изменяя существующие элементы в верхней части.

Применение атрибутов async и defer для тега script

Давайте разберёмся, что из себя представляет асинхронная и отложенная работа JavaScript и какая принципиальная разница между атрибутами async и defer. Но вначале рассмотрим последовательность обработки документа при обычном подключении тега <script>.

<script src="example.js"></script>

В наглядном примере я буду использовать следующие условные обозначения:

Парсинг — обработка страницы
Загрузка — загрузка скрипта
Выполнение — выполнение скрипта

Таким образом, последовательность обработки документа происходит по следующей схеме:

Script

Разбор HTML-кода прерывается на время загрузки и выполнения скрипта, после чего продолжается. Отображение веб-страницы происходит с задержкой.

Атрибут defer

Атрибут defer позволяет браузеру начать загрузку js-файлов параллельно, не останавливая дальнейшую обработку страницы. Их выполнение происходит после полного разбора объектной модели документа (от англ. Document Object Model, сокращенно DOM), при этом браузер гарантирует последовательность на основе порядка подключения файлов.

<script defer src="example.js"></script>

Схема последовательности обработки:

Script defer

Это отложенная загрузка. Данный атрибут рекомендуется применять при подключении нескольких JS файлов, при условии что один скрипт зависит от другого и вам важна последовательность их выполнения.

Атрибут async

Поддержка атрибута async появилась в HTML5, он разрешает браузеру загружать js-файлы параллельно и выполнять сразу после загрузки, не дожидаясь обработки остальной части страницы.

<script async src="example.js"></script>

Схема последовательности обработки:

Script async

Это асинхронная загрузка. Атрибут рекомендуется применять для таких скриптов, которые не оказывают значительного влияния на отображение документа. К ним относятся счётчики сбора статистики (Google Analytics, Яндекс Метрика), коды рекламных сетей (Рекламная сеть Яндекса, Google AdSense), кнопки социальных сетей и так далее.

Скорость загрузки сайта — один из факторов ранжирования в Google.

Асинхронное подключение JavaScript снижает время загрузки страниц за счёт отсутствия задержки. Наряду с этим я рекомендую сжимать и объединять js-файлы в один, например, с помощью библиотеки Minify. Пользователям нравятся быстрые сайты 😎

  1. 5
  2. 4
  3. 3
  4. 2
  5. 1
(13 голосов, в среднем: 4.4 из 5)
  1. Сергей

    Я у себя все скрипты отпустил вниз перед закрывающим тегом и в добавок половину скриптов перевел на асинхронную загрузку. Скорость выросла в разы, правда я делал эту оптимизацию давно.

    С недавнего времени заметил что кнопки поделиться от яндекса немного тормозят загрузку, нужно наверное искать альтернативу или собирать самому. Денис, а ты как реализовал кнопки поделиться у себя?

    Кстати про атрибут defer не знал, спасибо за инфу.

    Ответить

  2. Webliberty

    Сергей, кнопки Яндекса с относительно недавних пор подгружают скрипты Метрики. Директ тоже свою Метрику загружает, вот и начинает все жутко тормозить. Сторонние скрипты собирают свои данные и потом продают их рекламодателям, даже Share42, кажется, стал этим грешить… Поэтому использую другое решение, вскоре напишу об этом.

    Ответить

  3. Сергей Совков

    Вот за это огромное спасибо! Буду внедрять в свой блог 😎

    Ответить

  4. Сергей

    Webliberty, хорошо с интересом почитаю.

    Я нашел уже одно решение с кнопками, даже на одном проекте уже реализовал, с индивидуальным дизайном, все отлично работает но без счетчиков. Надо себе на сайт прикрутить будет. Правда хочется реализовать со счетчиком. Счетчики как бы информируют какой материал нравится читателю.

    Ответить

  5. Poison

    При анализе сайта часто вижу подобную проблему. Торможение ресурса из-за кодов в верхней части. Но не мог понять в чем именно. Сегодня ознакомился с детальной информацией, поэтому сразу последуют меры.

    Ответить

  6. Дмитрий

    Спасибо, очень помогли. В PageSpeed Insights результат сразу взлетел. Сначала пробовал async, но у меня именно нужно было чтобы JQuery грузился раньше. Defer решил проблему. Еще раз спасибо 😀

    Ответить

  7. Алексей

    Подскажите как лучше оптимизировать два скрипта, которые больше всего едят процессорное время: Yandex Metrica и Jivochat?

    Особенно критично при мобильной версии, у Метрики задержка 2173 ms!!! 😳

    Ответить

  8. Webliberty

    Алексей, внешними скриптами сложно управлять, ведь они размещены на другом сервере, доступа к которому нет. Быть может пора задуматься о смене хостинга, если он не справляется? Или справляется, но хочется получить хорошие результаты в Google PageSpeed Insights? 🙂

    Код счётчика Метрики можно вынести в отдельный файл и сохранить на своём сервере, тогда у вас появится возможность сжимать и кэшировать скрипт, но при любых изменениях со стороны Яндекса ваш локальный файл окажется неактуальным, перестанет собирать статистику или появятся сбои в его работе. На свой страх и риск. Здесь размещена инструкция как реализовать на практике.

    Про Jivochat ничего толкового не скажу, так как не пользовался, если скрипт размещается на вашем сервере, то только сжимать и кэшировать, не забывая про асинхронную загрузку. Дополнительно посмотрите в сторону Preload, Prefetch и Preconnect для предварительной загрузки данных.

    Ответить

  9. Алексей

    Здравствуйте! Хостинг справляется, просто хочется получить хороший результат в Google PageSpeed Insights 🙂

    Так чтобы Вы сделали? Или Ваша основная рекомендация — ничего не трогать — пусть работает как есть?

    Ответить

  10. Webliberty

    Алексей, я рекомендую сделать всё что в ваших силах, а не оставлять как есть.

    Для Метрики у меня в секции <head> заголовка сайта прописаны правила DNS Prefetch, что позволяет браузеру заранее обратиться к внешнему сайту для снижения задержки и увеличения производительности страницы:

    <link rel='dns-prefetch' href='https://mc.yandex.ru' />

    Выше в примере приведён только один URL, хотя на самом деле Метрика загружает несколько ресурсов с разных адресов — все можно прописать. Экспериментируйте!

    Ответить

:) ;) :D :( :cry: :| :o :P 8-) :oops: :roll: :idea:

Отправляя комментарий, вы соглашаетесь с политикой конфиденциальности.