Отложенная загрузка javascript – Асинхронная загрузка javascript файлов. Ускорение и оптимизация процесса, увеличение производительности

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

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

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

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

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

По этой причине анализатор скорости загрузки сайта Google 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. Пользователям нравятся быстрые сайты 😎

Асинхронная загрузка JavaScript - ускоряем загрузку страниц — LOCO.RU

Выход есть: поместить явавские строки в конец html документа (следовательно их загрузка будет происходить после прорисовки всей страницы) и только после этого содержимое блоков будет отображено в нужных местах. Это называется асинхронная загрузка JavaScript. Все серьезные проекты сегодня стараются как можно быстрее перейти на новую технологию загрузки. Тем более, что это абсолютно легко.

Есть несколько подходов. Начну по порядку.

JavaScript: синхронная загрузка скрипта

Загрузка javascript файла осуществляется так:

<script src="http://www.site.ru/script.js" type="text/javascript"></script>

Асинхронная загрузка скрипта HTML5

Стандарт HTML5 поддерживает возможность асинхронной загрузки скриптов, что может значительно ускорить общее время получения страницы. Просто добавьте async или defer.

<script async src="http://www.site.ru/script.js" type="text/javascript"></script>
<script defer src="http://www.site.ru/script.js" type="text/javascript"></script>

Чем же отличаются атрибуты async и defer

В обоих случаях мы получаем асинхронную загрузку скриптов. Разница заключается только в моменте, когда скрипт начинает выполнятся. Скрипт с атрибутом async выполнится при первой же возможности после его полной загрузки, но до загрузки объекта window. В случае использования атрибута defer – скрипт не нарушит порядок своего выполнения по отношению к остальным скриптам и его выполнение произойдет после полной загрузки и парсинга страницы, но до события DOMContentLoaded объекта document.

К сожалению, этот механизм на сегодняшний день не работает во всех браузерах (особенно это касается IE). Также не будет работать, если в файле script.js есть строки document.write.

Асинхронная загрузка javascript скриптом от Google

Как известно всем мастерам, Google уделяет особое внимание скорости загрузки сайтов, и понижает медленные в поисковой выдаче. Что бы помочь, Гугл разработал специальный скрипт, при помощи которого можно сделать асинхронную загрузку javascript.

Чтобы использовать, просто заменяем
<script src=”…”>
на
<script extsrc=”…”>

И подключаем файл скрипта

extsrc.js

Получится так:

<script src="http://extsrcjs.googlecode.com/svn/trunk/extsrc.js"></script>
<script extsrc="...."></script>

К сожалению, этот способ тоже не подойдет к файлам с document.write

Лучшая рабочая асинхронная загрузка javascript

Универсальный способ для всех браузеров. Работает даже с document.write

В том месте страницы, где нужно реально отобразить наш элемент создаем пустой div блок:

<div></div>

В самом конце страницы перед </body> вставляем скрипт для асинхронной загрузки файлов:

<div>

Здесь любой файл или скрипт, который нужно загрузить.</div>
 
<script type="text/javascript">
   // переместить его в реальную позицию отображения
   document.getElementById('script_block').appendChild(document.getElementById('script_ad'));

   // показать
   document.getElementById('script_ad').style.display = 'block';

</script>

В самых старых версиях IE (6 и ниже) асинхронная загрузка к сожалению не работает, но таких пользователей уже практически нет. Все остальные браузеры и сервисы успешно пользуются современной ускоренной загрузкой web-страниц.

Асинхронная загрузка JavaScript — ускоряем загрузку страниц

Современные веб-страницы сильно перегружены файлами javascript. Это ведет к замедлению загрузки и последующего отображения страницы. В худших условиях посетителю сайта приходится ждать до 30 секунд.

Современное использование JavaScript

Современные веб-страницы сильно перегружены файлами javascript. Это ведет к замедлению загрузки и последующего отображения страницы. В худших условиях (медленное подключение к Интернету, много javascript файлов) посетителю сайта приходится ждать до 30 секунд.

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

Таким образом, загрузка тормозится в местах с javascript строками.

Выход есть: поместить явавские строки в конец html документа (следовательно их загрузка будет происходить после прорисовки всей страницы) и только после этого содержимое блоков будет отображено в нужных местах. Это называется асинхронная загрузка JavaScript.

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

Есть несколько подходов. Начну по порядку.

JavaScript: синхронная загрузка скрипта

Загрузка javascript файла осуществляется так:

<script src="//www.site.ru/script.js" type="text/javascript"></script>

Асинхронная загрузка скрипта HTML5

Стандарт HTML5 поддерживает возможность асинхронной загрузки скриптов, что может значительно ускорить общее время получения страницы. Просто добавьте async или defer.

<script async src="//www.site.ru/script.js" type="text/javascript"></script>
<script defer src="//www.site.ru/script.js" type="text/javascript"></script>

Чем же отличаются атрибуты async и defer

В обоих случаях мы получаем асинхронную загрузку скриптов. Разница заключается только в моменте, когда скрипт начинает выполнятся. Скрипт с атрибутом async выполнится при первой же возможности после его полной загрузки, но до загрузки объекта window. В случае использования атрибута defer — скрипт не нарушит порядок своего выполнения по отношению к остальным скриптам и его выполнение произойдет после полной загрузки и парсинга страницы, но до события DOMContentLoaded объекта document.

К сожалению, этот механизм на сегодняшний день не работает во всех браузерах (особенно это касается IE). Также не будет работать, если в файле script.js есть строки document.write.

Асинхронная загрузка javascript скриптом от Google

Как известно всем мастерам, Google уделяет особое внимание скорости загрузки сайтов, и понижает медленные в поисковой выдаче. Что бы помочь, Гугл разработал специальный скрипт, при помощи которого можно сделать асинхронную загрузку javascript.

Чтобы использовать, просто заменяем
<script src=»…»>
на
<script extsrc=»…»>

И подключаем файл скрипта extsrc.js

Получится так:

<script src="//extsrcjs.googlecode.com/svn/trunk/extsrc.js"></script>
<script extsrc="...."></script>

К сожалению, этот способ тоже не подойдет к файлам с document.write

Лучшая рабочая асинхронная загрузка javascript

Универсальный способ для всех браузеров. Работает даже с document.write

В том месте страницы, где нужно реально отобразить наш элемент создаем пустой div блок:

<div></div>

В самом конце страницы перед </body> вставляем скрипт для асинхронной загрузки файлов:

<div>
Здесь любой файл или скрипт, который нужно загрузить.</div>
 
<script type="text/javascript">
   // переместить его в реальную позицию отображения
   document.getElementById('script_block').appendChild(document.getElementById('script_ad'));
   // показать
   document.getElementById('script_ad').style.display = 'block';
</script>

В самых старых версиях IE (6 и ниже) асинхронная загрузка к сожалению не работает, но таких пользователей уже практически нет. Все остальные браузеры и сервисы успешно пользуются современной ускоренной загрузкой web-страниц.

Хостинг и VPS которые никогда не тормозят

Рекомендую самый быстрый VPS на немецких серверах за разумные деньги — FastVPS

Асинхронная и отложенная работа Javascript — Оптимизируем работу сайта

Большинство (если не все) современных сайтов используют Javascript. Кнопки социальных сетей? Плагины? Даже шаблоны! В 99% случаев эти компоненты будут использовать Javascript. Это означает, что на ваших сайтах используются скрипты. Но скрипты замедляют скорость работы сайта. Сегодня мы хотим представить вам 2 плагина, которые позаботятся об этой проблеме.

Асинхронное и отложенное… что?

Перед тем, как мы начнем, вам следует учитывать три вещи:

  1. Parser – это HTML в стадии загрузки
  2. Net – это время, за которое загружается ваш скрипт
  3. Execution – это время, за которое скрипт полностью загружен для работы в браузере.

В рамках обычной среды работы сайта HTML парсинг приостанавливается на время выполнения скриптов. Если ваш сайт похож на мой, то это означает, что пользователь, перед тем, как сможет воспользоваться вашим сайтом, должен будет немного подождать (загрузки вашего кода, дизайна, контента и так далее). Давайте взглянем на то, как выглядит обычная загрузка скрипта:

Отложенная загрузка просто позволяет вашему коду HTML загрузиться до того, как начнут выполять работу скрипты. Здесь преимущество заключается в том, что  сайт мгновенно будет отображен в окне браузера, как бы демонстрируя молниеносную производительность. Лично я рекомендую использовать отложенную загрузку в тех случаях, если некоторые ваши пользователи используют браузеры, где отсутствует поддержка асинхронной загрузки скриптов. Давайте взглянем на то, как работает отложенная загрузка:

Асинхронная загрузка скриптов – это лучшая опция. HTML-парсинг и загрузка скриптов будет продолжаться, но выполнение скриптов будет возможным только тогда, когда вся загрузка будет завершена. Это позволит вам максимально быстро представить контент сайта вниманию посетителей. Однако не все браузеры поддерживают асинхронную загрузку скриптов. Давайте взглянем на то, как происходит асинхронная загрузка:

  • Я, конечно же, рекомендую вам оптимизировать  скрипты, используя оба метода.

При использовании этих атрибутов, вам будут доступны 3 режима. Если вы используете атрибут async, то скрипт будет выполняться асинхронно, как только это станет возможным. Если вы не используете атрибут async, и вместо этого используете defer, то скрипт будет выполняться тогда, когда закончится парсинг страницы. Если вы не используете ни один из этих атрибутов, то скрипт будет загружаться и выполняться мгновенно, еще до того, как браузер начнет парсинг страницы.

С чего начать?

Итак, если Асинхронный javascript – это лучшая опция, позвольте представить вам лучший WordPress-плагин для асинхронной загрузки Javascript. Кто бы мог подумать, что называется он Asynchronous Javascript!

Скачайте его, установите и – вы готовы к работе! Однако он будет конфликтовать с некоторыми плагинами, особенно если вы используете слайдеры. В настройках шаблонов WordPress зачасту присутствует такая функция. Вы можете исключить скрипты, которые должны загружаться мгновенно.

Далее хочется перейти к отложенной загрузке Javascript. Я познакомился с плагинами, и мне показалось, что лучше всего работают плагины с точным соответствием названий. Лучшим в данной категории мне показался плагин под названием WP Deferred Javascript.

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

Источник: http://marafonec.com/

Алексей Повловский

Как оптимизировать загрузку js для многостраничных сайтов? — Хабр Q&A

Благодаря обсуждению в комментариях и еще некоторым изысканиям я пришел к следующему. Во-первых, вопрос оптимизации нужно разделить на 2 пункта и каждый из них обсудить отдельно.
1. Загрузка скриптов на устройство пользователя. Здесь однозначный вариант одобренный всеми - объединить все скрипты в один файл, минифицировать его, сжать и положить в кэш пользователю при первом визите.
2. Выполнение скриптов на устройстве пользователя. Здесь сложнее. Во-первых, оно происходит на каждое открытие страницы независимо от того взят скрипт из кэша или нет. Если вы не проводили никакой оптимизации, а просто объединили все свои скрипты в один файл, то сразу же после загрузки (взятия из кэша) браузер пользователя начнет их анализ и выполнение. Это занимает время, а на это время браузер пользователя "замирает". В зависимости от мощности устройства (десктоп или телефон) и размера вашего объединенного яваскрипта это выполнение можно занимать от долей секунды до нескольких секунд. Но даже замирание в 0.2-0.3 секунды вполне заметно для пользователя.
Полезные ссылки по этой теме:
calendar.perfplanet.com/2011/lazy-evaluation-of-co...
habrahabr.ru/post/145269

Остается вопрос, как совместить первое и второе, т.е. отдать пользователю весь js в одном большом файле, но заставить браузер выполнять только нужный на данной странице код, а ненужный не выполнять. Решение этому есть! Называется отложенное (ленивое) выполнение яваскрипта, по английски, delay (lazy) javascript evaluation. Т.е. если вы весь код объединяете в один файл и у вас этого кода много, позаботьтесь о том, чтобы выполнялся только тот код, который нужен на текущей странице.

В интернете достаточно решений по этому поводу, но т.к. мы используем require.js, я смотрел, как это решено в данной библиотеке. Начиная со 2 версии require.js умеет откладывать выполнение яваскрипта и делает это автоматически для всех модулей объявленных через define. Важно знать, что для скриптов написанных не в формате AMD и подключенных через shim (например плагинов jquery) отложенное выполнение не работает и они выполняются сразу же при загрузке. К сожалению, у нас таких плагинов довольно много и придется что-то делать, например, оборачивать их в модули requirejs. Но, кажется, это не очень большая проблема.

В итоге короткий ответ на вопрос такой: пакуем все скрипты в один файл, но обязательно заботимся об отложенном выполнении скриптов, чтобы не нагружать браузер лишней работой, а пользователя задержками на выполнение ненужного яваскрипта.

Параллельная загрузка JavaScript и CSS без блокирования парсинга страницы / Habr

Известно, что следуя идеям старой школы, а именно, добавляя ссылки на JS и CSS в страницы, может обернуться большим временем загрузки страницы. Браузер отображает страницу по мере скачивания, но останавливается, если натыкается на тег script со ссылкой, до того момента, пока скрипт не будет загружен и выполнен. Сайты стали использовать всё большее количество скриптов, начальное отображение страницы занимает всё больше времени, к примеру, на этой странице, которую вы читаете, 13 скриптов, 7 из которых находятся в head'е. Ко всему прочему, некоторые браузеры по-прежнему придерживаются ограничений на одновременное количество загрузок с одного хоста.

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

Существует несколько решений, как то:
— поместить стили и скрипты прямо в страницу;
— установка аттрибутов async/defer тегу script;
— склеить все скрипты в один файл;
— помесить ссылки на скрипты в конец body;
— разместить все файлы на CDN/на разных хостах;
— свой вариант…

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

Началось всё, конечно, с того, что я взялся за один проект, и в какой-то момент мне показалось, что простенькая страница достаточно долго загружается, и посмотрел на график загрузки, и на результаты YSlow. Огонь на секунду потух в моих глазах, но зная, что может быть лучше, я полез искать,

Разберём недостатки перечисленных выше методик.

Помещение скриптов и стилей прямо в страницу

Очевидно, что это решение подходит только для маленьких страниц, где не много скриптов стилей, так как в случае перезагрузки страницы будут повторно загружаться статические данные, и кеширование не может сработать. Решение вполне оправдано для небольших скриптов и стилей, жизненно необходимых с того самого момента, как страница загружена.
Установка аттрибутов async/defer тегу script

Спецификация тут.
Аттрибуты async и defer тега script поддерживается следующими бразуерами, что может показаться недостаточным для тех, кто делает сайты, на которые могут заходить люди с устаревшими браузерами, а также Opera, что особенно актуально в рунете.
Из недостатков также можно отметить, что скрипты, загруженные из тега с аттрибутом defer, не могут использовать document.write, так как их исполнение не синохронизировано с парсером страницы.
Склеивание скриптов и стилей

Есть интересная заметка (осторожно, англ.) и тест, которые показывают, что загрузка одного большого файла может длиться дольше, чем параллельная загрузка отдельных файлов. Однако, эта техника не только достойна упоминания и жизни, но и также крайне показана к применению в том случае, если разные страницы сайта используют один и тот же набор скриптов или стилей.
Помещение stylesheet в head, а script — в конец body

Достойно упоминания и использования, но в этом случае, как и в описанных выше, до момента document.ready могут быть неразрешённые зависимости между скриптами, и если для jQuery с плагинами это допустимо, то для варианта, когда мы загружаем библиотеку API Facebook'а или VKontakte, и хотим тут же запустить наш скрипт, который пошёт на API запрос определения, залогинен ли пользователь, это сулит костылями, либо загрузкой библиотеки API в начале страницы, блокируя её отображение, что отягощается необходимостью вызова DNS resolve.
Загрузка с CDN

Использование CDN может снизить загрузку на собственный сервер, но может и увеличить и уменьшить время загрузки, а может и полностью блокировать загрузку скрипта, как в случае атаки на CDN сервер или блокировки CDN сервера на провайдере или в сети предприятия.
Какие ещё есть решения?

Что если попробовать загружать скрипты в тот момент, пока страница грузится, но не выполнять их, и вообще скрывать от браузера, что это скрипты до того момента, пока они не догрузились, чтобы не блокировать первичное отображение страницы?

Где-то в заметках у меня нашёлся HeadJS, но с тех пор, как я впервые на него наткнулся, он серьёзно заматерел, и научился делать не только то, что нам нужно, но и многое другое. Несмотря на то, что библиотека явно хороша, а в минифицированном виде занимает всего 3КБ, я решил поискать альтернатив и нашёл аж 14 аналогичных библиотек, краткое и не всегда верное сравнение которых можно найти в этой заметке, плюс load.js и include.js. Бегло пробежавшись по представленным библиотекам и отметя сначала большие (>3КБ), а потом те, которые не понравились мне по синтаксису или принципу работы, я лично для себя выбрал YepNope.js, входящий в состав Modernizr. Авторы библиотеки сообщают, что библиотека не лучше и не хуже остальных, и выполняет ту же задачу, что и остальные, и что они сами в разных проектах используют также и другие загрузчики.

Итак, что же и как делает загрузчик ресурсов на примере YepNope:

<script src='/javascripts/yepnope-min.js'>
  yepnope('/javascripts/jquery.min.js', '/javascripts/jquery.loadmask.min.js', '/javascripts/jquery.jgrowl_minimized.js'])
</script>

Исполнение загруженных скриптов идёт в указанном порядке.

Далее в блоке инициализации:

yepnope({
  load: ['//connect.facebook.net/ru_RU/all.js', '/javascripts/facebook_auth_callback.js'],
  complete: function(){
    FB.init({appId: '273684999999999', xfbml: true, cookie: true, oauth: true})
    FB.Event.subscribe('auth.statusChange', facebook_auth)
  }
})

Итак, мы получаем все желаемые плюшки, как то параллельная загрузка, определённость времени выполнения скрипта, зависиммости, обратные вызовы по готовности.

Пример загрузки стилей:

yepnope(['/stylesheets/jquery.loadmask.css', '/stylesheets/jquery.jgrowl.css'])

У YepNope и других загрузчиков есть также много дополнительных возможностей, описание которых в этом топике не уместно, но с которыми неплохо познакомиться, и каждому выбрать что-то для себя самому.

Авторы скриптов не могут прийти к единому принципу работы и интерфейсу API, и продолжают создавать всё новые загрузч ики. В связи с этим автор HeadJS предлагает встроить поддержку порядка загрузки в спецификации, и автор $script.js его в этом поддерживает, но пока это пройдёт через спецификации и будет работать одинаково во всех браузерах, нам предстоит пользоваться загрузчиками.

Каков же итоговый рецепт?
— встроить в head страницы script, указывающий на загрузчик;
— встроить inline скрипт, использующий загрузчик для подгрузки других скриптов и стилей;
— объединять скрипты и стили, использующиеся только совместно, в один для минимизации количества HTTP запросов;
— минимизировать скрипты и стили;
— убедиться в том, что сервер пакует передаваемые данные gzip'ом;
— убедиться в том, что сервер правильно кеширует;
— осторожно и вдумчиво использовать сторонние CDN и дополнительные хосты.

При написании топика делал оглядку на следующие материалы, рекоммендуемые к прочтению:
[1]. Очерёдность событий и синхронизация в JavaScript
[2]. Простая загрузка скрипта при помощи yepnope.js
[3]. Описание yepnope.js
[4]. Описание $script.js

UPD.
от sHinE Ещё одна таблица-сравнение различных загрузчиков, с более полным списком.
от S2nek Русский перевод описания YepNope.

Отправить ответ

avatar
  Подписаться  
Уведомление о