Загрузка JavaScript(без блокировки отрисовки документа, асинхронная загрузка). Асинхронная загрузка JavaScript - ускоряем загрузку страниц

Способ ускорить загрузку веб-станиц сайта путем оптимизации джава скрипт файлов и html кода страницы.

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

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

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

Решение проблемы - асинхронная загрузка. Просто разместите javascript в конце html-кода страницы. Это приведет к тому, что загрузка «явы» будет отдалена по времени, обеспечивая корректное отображение страницы и быстрый страт для пользователей ресурса. На асинхронную загрузку переходят большинство серьезных ресурсов, старающихся сохранить аудиторию и внедрить полезное нововведение.

Разберем несколько способов оптимизации загрузки javascript.

Такая загрука javascript-файла осуществляется следующим образом:

< script src= type= "text/javascript" >

HTML5 предусмотрительно озаботился проблемой загрузки страницы с «явой». В нем есть возможность установить асинхронную загрузку скрипта, что увеличивает скорость отображения ресурса в разы. Для этого в html-код следует добавить параметры async или defer , как это указано ниже:

< script async src= "//www.адрес_сайта/script.js" type= "text/javascript" >

< script defer src= "//www.адрес_сайта/script.js" type= "text/javascript" >

В чем разница между атрибутами async и defer?

Оба параметра работают с асинхронной загрузкой javascript. Различие состоит во времени отображения и начале выполнения работы скрипта.

Атрибут async запустит скрипт сразу же, после полной загрузки, но при этом пропустит загрузку window.

При установке в код страницы атрибута defer - javascript встанет в очередь между другими скриптами, не нарушая их порядок выполнения. Он начнет работу только после полной загрузки страницы, но пропустит событие DOMContentLoaded (объект document).

Однако, данные атрибуты не работают в некоторых современных браузерах. Так, например, InternetExplorer не поддерживает атрибуты async и defer. А строки document.write ничем не помогут в файлах script.js

Специальный скрипт от Google для асинхронной загрузки javascript

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

Чтобы применить данный скрипт, просто заменяем

на

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

Получаем следующий код:

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

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

Этот способ подойдет для всех браузеров без исключения и работает даже с document.write

В html-коде страницы создаем пустой div-блок:

А в конце html-кода, перед , вставляем скрипт для асинхронной загрузки:

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

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

Примечание: ниже расположен перевод статьи от Steve Souders (автора знаменитых советов Yahoo! касательно клиентской производительности) "Coupling async scripts" . Steve анализирует поведение JavaScript-файлов при загрузке и предлагает несколько путей для обхода их «блокирующих» свойств. Мои комментарии далее курсивом.

Большая часть моей работы в последнее время была посвящена асинхронной загрузке внешних скриптов . Если скрипты загружаются в обычном порядке (), то они блокируют загрузку всех остальных компонентов страницы (в последних версиях Firefox и в Safari это не так, но речь идет, в основном, про 70% пользователей с IE ) и блокируют отрисовку всей той части страницы, которая расположена ниже вызова скриптов по HTML-коду. Это можно увидеть на тестовой странице размещаем скрипты внизунапример, при помощи динамического создания объектов после срабатывания комбинированного события window.onload ) предотвращает такое поведение браузера, что ускоряет загрузку страницы.

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

Существует несколько (стандартных ) путей для стыковки асинхронно загружаемых скриптов с другим JavaScript-кодом:

  • window onload . Выполнение внутреннего JavaScript-кода может быть привязано к событию window onload . Это очень просто в использовании, но часть скриптов может быть выполнена раньше.
  • onreadystatechange у скрипта . Внутренний код может быть привязан к событию onreadystatechange и(ли) onload . (Необходимо будет использовать оба варианта, чтобы покрыть все популярные браузеры.) В этом случае кода будет больше, он будет более сложным, но будет гарантия, что он исполнится сразу после загрузки соответствующих внешних файлов.
  • Встроенные вызовы . Внешние скрипты могут быть модифицированы таким образом, чтобы включать в самом конце вызов небольшого участка кода, который вызовет соответствующую функцию из внутреннего кода. Это все замечательно, если внешние и внутренние скрипты разрабатываются одной и той же командой. Но в случае использования сторонних разработок, это не обеспечит всей необходимой гибкости для связки внешних скриптов с внутренним кодом.

В этой заметке я параллельно (никакого каламбура!) освещаю два вопроса: как асинхронные скрипты ускоряют загрузку страницы и как можно состыковать асинхронные скрипты и внутренние используя модифицированный вариант загрузчика от John Resig (автора jQuery ) — шаблон двойного тэга script . В качестве иллюстрации этого можно привести мою недавнюю работу по сортировке результатов UA Profiler . Я выполнил ее при помощи скрипта сортировочного скрипта от Stuart Langridge. Примерно за 5 минут я смог добавить его скрипт на страницу для сортировки таблицы с результатами. Затратив немного больше времени, я смог сделать загрузку этого скрипта асинхронной и ускорить загрузку страницы более чем на 30%, используя технику стыковки асинхронных скриптов.

Обычные вызовы скриптов

Изначально я добавил сортирующий скрипт Stuart Langridge на страницу UA Profiler обычным способом (через ), это можно увидеть на варианте с обычным вызовом скрипта . Диаграмма загрузки изображена на рис. 1.

Рис. 1. Диаграмма загрузки скриптов в обычном случае.

Хотя сортировка данных в таблице и работала, это не сделало меня счастливее, ибо загрузка страницы замедлилась. На рис. 1 хорошо видно, как моя версия скрипта (по имени sorttable-async.js) блокирует все остальные HTTP-запросы на странице (в частности, arrow-right-20x9.gif), что замедляет загрузку страницы. Все диаграммы загрузки сняты при помощи Firebug 1.3 beta . В этой версии Firebug красной линией отображается событие onload . (А синяя линия соответствует событию domcontentloaded .) Для версии с обычным вызовом скрипта событие onload срабатывает на 487 миллисекунде.

Скрипт sorttable-async.js не является необходимым для первоначального отображения страницы: сортировка столбцов возможна только после того, как сами столбцы отрисованы. Такая ситуация (внешние скрипты, которые не используются для первоначального отображения страницы) является кандидатом номер 1 для внедрения асинхронной загрузки. Вариант с асинхронной загрузкой скриптов подключает этот скрипт, используя DOM-методы для создания нового тега script:

var script = document.createElement("script"); script.src = "sorttable-async.js"; script.text = "sorttable.init()"; // это объясняется в следующем разделе document.getElementsByTagName("head").appendChild(script);

Диаграмма HTTP-загрузки для асинхронной загрузки скриптов изображена на рис. 2. Стоит обратить внимание, как асинхронный подход предотвращает блокирующее поведение: sorttable-async.js и arrow-right-20x9.gif загружаются параллельно. Это снижает общее время загрузки дл 429 мс.

Рис. 2. Диаграмма загрузки скриптов в асинхронном случае

Шаблон двойного скрипта от John Resig

Позволяет укорить загрузку страницы, но в этом случае остается, что улучшить. По умолчанию сортирующий скрипт вызывает «сам себя» при помощи прикрепления sorttable.init() в обработчику события onload для этого скрипта. Некоторое улучшения производительности (и уменьшение кода ) может быть достигнуто, если вызвать sorttable.init() внутри тега script , чтобы вызвать его сразу же после загрузки внешнего скрипта (подключенного через src ). В этом случае в качестве "API" я использую одну-единственную функцию, но я предполагаю, что этот случай иллюстрирует максимально расширяемый шаблон, позволяющий использовать внешний модуль безо всяких предположений о его дальнейшем использовании (классическая ситуация использования JavaScript-логики от внешних разработчиков ).

Я уже описал три способа по стыковке внутреннего кода с асинхронной загрузкой внешних скриптов: window onload , onreadystatechange у скрипта и встроенный в скрипт обработчик. Вместо всего этого я использовал технику от John Resig — шаблон двойного тэга script . John описывает, как связать внутренние скрипты с загрузкой внешнего файла следующим образом:

jQuery("p").addClass("pretty");

В этом случае код внутри срабатывает только после того, как загрузка (и инициализация ) внешнего скрипта завершилась. У этого подхода по стыковке скриптов есть несколько очевидных преимуществ:

  • проще: один тег script вместо двух
  • прозрачнее: связь внутреннего и внешнего кода более очевидная
  • безопаснее: если внешний скрипт не загрузится, внутренний код не будет выполнен, что предотвратит появление ошибок, связанных с неопределенными переменными

Это замечательный шаблон для асинхронной загрузки внешних скриптов. Однако чтобы его использовать нам придется внести изменения как во внутренний код, так и во внешний файл. Для внутреннего кода мне пришлось добавить уже упомянутую выше третью строку, которая выставляет свойство script.text . Для завершения процесса стыковки нужно добавить в конец sorttable-async.js:

var scripts = document.getElementsByTagName("script"); var cntr = scripts.length; while (cntr) { var curScript = scripts; if (-1 != curScript.src.indexOf("sorttable-async.js")) { eval(curScript.innerHTML); break; } cntr--; }

Этот код проходится по всем скриптам на странице, находит необходимый блок, который должен загрузить сам себя (в этом случае это скрипт с src содержащим sorttable-async.js). Затем он выполняет код, которые добавлен к скрипту (в этом случае sorttable.init()) и таким образом вызывает сам себя. (Небольшое замечание: хотя при загрузке скрипта текст в нем был добавлен при помощи свойства text , обращение к нему происходит при помощи свойства innerHTML . Это необходимо для обеспечения кроссбраузерности.) При помощи такой оптимизации мы можем загрузить внешний файл скрипта, не блокируя загрузку других ресурсов, и максимально быстро выполнить привязанный к данному скрипту внутренний код.

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

var _on_ready_execution = setInterval(function() { if (typeof urchinTracker === function) { urchinTracker(); clearInterval(_on_ready_execution); } }, 10);

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

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

Ленивая загрузка

Общее время загрузки может быть уменьшено еще больше, если использовать «ленивую загрузку» скрипта (загружать его динамически как часть обработчика события onload). Пример такого поведения расположен на странице с

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

Ускоряем загрузку html страниц

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Чтобы использовать, просто заменяем

на

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

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

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

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

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

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

< div id= "script_block" class = "script_block" >

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

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

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

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

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

script src= type= "text/javascript" >

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

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

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

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

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

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

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

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

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

Чтобы использовать, просто заменяем

на

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

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

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

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

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

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

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

< div id= "script_block" class = "script_block" >

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

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

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

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

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

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

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

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

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

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

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

1 < src = "example.js" >

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

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

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

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

Атрибут defer

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

1 < defer src = "example.js" >

Атрибут async

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

1 < async src = "example.js" >

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

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

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

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



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: