Что такое асинхронная загрузка. Шаблон двойного скрипта от John Resig

Выход есть: поместить явавские строки в конец 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-страниц.

Иногда возникает необходимость в поэтапной асинхронной загрузке данных. И это может быть все, что угодно. Начиная от загрузки зависимых справочников (например, страна -> города), заканчивая объединением и обработкой информации с различных источников (например, вы используете несколько разных сервисов, и каждый из них тратит разное время на формирование данных).

А теперь чуть попроще.

Проблематика поэтапной асинхронной загрузки данных в jQuery (ajax)

Если вам надо связать несколько последовательно выполняемых ajax-запросов в jQuery, то самым простым решением будет - сделать вызов следующей функции в конце каждого обработчика success. Это не только достаточно просто, но и не вызывает никаких проблем. Например,

// Первый запрос $.ajax(url, { ... success: function (result) { // Какой то код... // Вызов следующего обработчика nextLoader(); } });

А теперь, допустим, перед вами стоит чуть более сложная задача. Например, вам необходимо запустить функцию только после того, как выполнятся несколько асинхронных запросов (например, получение пузомерок для сайта). Конечно, их так же можно связать в прямую цепочку, как это было показано выше. Но, при этом начинает теряться сама суть асинхронности. И так же может получиться, что вы строите зависимость между совершенно не связанными блоками. Согласитесь, что показатель тИЦ и данные по whois не совсем зависят друг от друга.

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

Но, что вы будете делать, если ваша задаче окажется еще сложнее? Когда вам необходимо все операции и загрузки данных распределить по этапам. Например, вы составляете формочку диалога. На первом этапе будет идти получение данных для всех полей (выпадающие списки, группы чекбоксов и т.д.). На втором этапе будет происходить определение обработчиков для созданных полей. А на третьем этапе, уже после полной загрузки "всё и вся", открывать доступ к различным кнопкам и другим элементам интерфейса (чтобы шаловливые ручки не создали вам кучи проблем). Чисто визуально это может выглядеть так:

Согласитесь, что организовать вызов всех функций в одну цепочку - ни только не простое занятие, но еще и не очень приятное. Кроме этого еще представьте, что вам надо добавить несколько полей и различных обработчиков. Что будет? У вас начнет голова закипать от поиска нужных мест "куда вставить". Тут уже нужен какой-то механизм, который позволит вам выстроить все запуски поэтапно.

Пишем скрипт для организации поэтапной асинхронной загрузки в jQuery

Первым делом необходимо определиться с вполне логичным вопросом "почему не использовать готовые библиотеки?". Как такового, ответа на этот вопрос не существует. Все очень сильно зависит от задачи. Так как слово "библиотека" обычно подразумевает:

  • отсутствие управляемости кода (вы не можете поменять внутреннюю логику библиотеки; а если вы это сделаете, то любое изменение может сильно "аукнуться" в будущем)
  • необходимость изучения ее базовый свойств и принципов (обычно, это сводится к прочтению всей возможной документации и куче различных тестов)
  • ограничения на версии jQuery (если используются сложные ядровые механизмы, то возможно привязка к версии библиотек jQuery)
  • возможные проблемы совместимости с другими скриптами (далеко не факт, что библиотека будет корректно себя вести с другими библиотеками)
  • чрезмерное богатство функциональности, и как следствие наличие "дополнительных ограничений"
  • и т.д.

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

Именно, поэтому необходимо сначала определиться с вашими задачами (количество, частота возникновения), со временем (сколько вы готовы потратить на решение задачи), чем вы готовы пожертвовать (важна ли для вас возможность быстро что-то подправить; важен ли размер библиотек; насколько ограничения вас устраивают), предпочтениями (например, вы принципиально не используете библиотеки). И уже только после того, как вы ответите себе на эти вопросы, пытаться ответить на вопрос "почему стоит или не стоит использовать готовые библиотеки?".

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

Если же вы полны энтузиазма и решимости, то преступим к дальнейшим действиям.

Составляем требования к скрипту

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

  • Подключение и настройка скрипта должны происходить автоматически (вам необходимо подключить лишь файл js)
  • Повторное подключение файла скрипта не должно вызывать сбой
  • Использовать только стандартные механизмы jQuery
  • Интерфейс должен быть простым и понятным
  • Вы можете составлять несколько независимых цепочек этапов
  • У вас всегда должна быть возможность быстро подкорректировать действия скрипта
  • Скрипт не должен накладывать сложные ограничения на ваш код (максимально - необходимость в добавлении функции оповещения о своем выполнении)

Примечание : Всегда формируйте требования так, чтобы при реализации не начать заниматься тем, что вообще не требуется. И обязательно включайте в него "итак понятные" пункты, чтобы эти пункты и дальше оставались "итак понятными".

Составляем тестовый проект

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

  • css - каталог со стилями
  • images - каталог с картинками (для визуального эффекта)
    • ajax-loader.gif - картинка загрузки
  • js - каталог со скриптами
    • jquery-ajax-stage.js - скрипт для поэтапной загрузки
  • data.json - тестовые данные
  • index.html - начальная страница

Примечание : При составлении структуры тестового проекта, старайтесь максимально приблизить ее к структуре настоящего проекта. Это поможет вам отловить проблемы, связанные со структурой, еще на этапе разработке.

Файл с тестовыми данными - data.json

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

{ data: "Много данных" }

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

Файл стилей - template.css

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

Left-table { float: left; padding-right: 10px; } .right-table { float: left; padding-right: 10px; } table.table-loader { border-spacing: 0px; border-collapse: collapse; width: 300px; } table.table-loader tr td { padding: 5px; border: 1px solid #ccc; }

Файл скрипта для поэтапной асинхронной загрузки - jquery-ajax-stage.js

Сама реализация поэтапной асинхронной загрузки.

(function (parentObject) { // Защита от повторного определения if(parentObject.eventManager) return; // Определяем объект parentObject.eventManager = { // Добавляем этап addStage: function (el, stageName) { var elCount = $(el).length; // Проверяем корректность параметров if(elCount > 0 && !!stageName) { // Такой этап уже есть if (($(el).get(0).eventStages = $(el).get(0).eventStages || {})) return; // Определяем "nfg $(el).get(0).eventStages = { waiterCount: 0, // Счетчик объектов находящихся в состоянии ожидания данных onEvent: // в данном массиве будут хранится все функции для вызова }; } }, // Удаляем этап removeStage: function (el, stageName) { var elCount = $(el).length; // Проверяем корректность параметров if(elCount > 0 && !!stageName) { // Такой этап нашелся if (($(el).get(0).eventStages = $(el).get(0).eventStages || {})) { delete ($(el).get(0).eventStages = $(el).get(0).eventStages || {}); ($(el).get(0).eventStages = $(el).get(0).eventStages || {}) = null; } } }, // Увеличиваем счетчик выполняемых функций для этапа addStageWaiter: function (el, stageName) { var elCount = $(el).length, stage = ($(el).get(0).eventStages = $(el).get(0).eventStages || {}); // Проверяем корректность параметров if(elCount > 0 && !!stageName && stage) { // Увеличиваем счетчик загрузок stage.waiterCount++; } }, // Уменьшаем счетчик выполняемых функций для этапа // Т.е. оповещаем, что функция выполнилась removeStageWaiter: function (el, stageName) { var elCount = $(el).length, stage = ($(el).get(0).eventStages = $(el).get(0).eventStages || {}); // Проверяем корректность параметров if(elCount > 0 && !!stageName && stage) { // Уменьшаем счетчик загрузок stage.waiterCount--; // Проверяем состояние этапа this.checkStage(el, stageName); } }, // Проверяем состояние этапа checkStage: function (el, stageName) { var elCount = $(el).length, stage = ($(el).get(0).eventStages = $(el).get(0).eventStages || {}); // Проверяем корректность параметров if(elCount > 0 && !!stageName && stage) { if (stage.waiterCount 0) { // Очередь FIFO - первый вошел, первым вышел, как в магазине stage.onEvent.shift()(); } } } }, // Добавляем вызов функции, который запустится при выполнении всего этапа onLoadStage: function (el, stageName, funcHandler) { var elCount = $(el).length, stage = ($(el).get(0).eventStages = $(el).get(0).eventStages || {}); // Проверяем корректность параметров if(elCount > 0 && !!stageName && stage && typeof (funcHandler) === "function") { // Добавляем обработчик stage.onEvent.push(funcHandler); // Проверяем состояние этапа this.checkStage(el, stageName); } } }; })(window);

Тестовая страница - index.html

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

Подключаем все необходимые файлы:

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

Начать загрузку

Определим функцию, которая будет создавать тестовые функции для этапов:

function getFakeLoader(storage, currStage, startDate, selector) { return function () { setTimeout(function () { $.ajax("data.json?callback=?", { contentType: "text/plain; charset=utf-8", dataType: "jsonp", jsonpCallback: function (result) { $(selector).html("Время от начала: " + ((+new Date() - startDate)/1000.0).toFixed(2) + " секунд"); // Пишем время загрузки window.eventManager.removeStageWaiter(storage, currStage); // Уменьшаем счетчик } }); }, Math.random() * (3000) + 1000 // Задежрка от 1 до 4 секунд); }; }

Создаем функцию, которая будет описывать логику для каждого тестового блока:

function formTestFor(selector) { $(selector + " .start-process").click(function () { var startDate = new Date(); // Для красоты добавим картинки setLoaderImgs(selector); // Определим этапы window.eventManager.addStage($(selector + " .table-loader"), "1"); window.eventManager.addStage($(selector + " .table-loader"), "2"); window.eventManager.addStage($(selector + " .table-loader"), "3"); // Заблокируем кнопку до конца этапа $(selector + " .start-process").attr("disabled", "disabled"); // Наполним очередь ожидания по 3 загрузки на стейдж // По факту эти действия должны происходить в местах запуска функций этапов window.eventManager.addStageWaiter($(selector + " .table-loader"), "1"); ... window.eventManager.addStageWaiter($(selector + " .table-loader"), "3"); // Теперь создадим в обратном порядке (для наглядности) функции загрузки // По факту эти действия должны происходить в местах определения функций window.eventManager.onLoadStage($(selector + " .table-loader"), "2", getFakeLoader($(selector + " .table-loader"), "3", startDate, selector + " .row-3 .td-1")); ... window.eventManager.onLoadStage($(selector + " .table-loader"), "1", getFakeLoader($(selector + " .table-loader"), "2", startDate, selector + " .row-2 .td-3")); // Добавим обычный текстовый вывод готовых этапов window.eventManager.onLoadStage($(selector + " .table-loader"), "1", function () { $(selector + " .row-1-end td").html("Первый этап закочнился за " + ((+new Date() - startDate)/1000.0).toFixed(2) + " секунд. Начинается следующий этап."); }); ... window.eventManager.onLoadStage($(selector + " .table-loader"), "3", function () { $(selector + " .row-3-end td").html("Третий этап закочнился за " + ((+new Date() - startDate)/1000.0).toFixed(2) + " секунд.
Загрузка окончена"); }); // После окончания третьего этапа разблокируем кнопку onLoadStage window.eventManager.onLoadStage($(selector + " .table-loader"), "3", function () { // Разблокируем кнопку $(selector + " .start-process").attr("disabled", null); }); // Теперь запустим функции первого этапа getFakeLoader($(selector + " .table-loader"), "1", startDate, selector + " .row-1 .td-1")(); getFakeLoader($(selector + " .table-loader"), "1", startDate, selector + " .row-1 .td-2")(); getFakeLoader($(selector + " .table-loader"), "1", startDate, selector + " .row-1 .td-3")(); // Наблюдаем... }); }

Теперь собираем все файлы в проект и переходим к первичному тестированию и демонстрации.

Смотрим результат

Открываем файл index.html в браузере. Должен отобразиться следующий интерфейс:

Как видно, нам доступно две кнопки для запуска параллельных процессов. После нажатия на них, должна начаться загрузка для соответствующих блоков. И выглядеть это будет примерно так:

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

Закончив первичное тестирование, переходим к проверке требований:

  • Подключение и настройка скрипта должны происходить автоматически (вам необходимо подключить лишь файл js) - Есть
  • Повторное подключение файла скрипта не должно вызывать сбой - Есть
  • Использовать только стандартные механизмы jQuery - Есть (использовался только функционал селекторов)
  • Интерфейс должен быть простым и понятным - Есть
  • Вы можете составлять несколько независимых цепочек этапов - Есть
  • У вас всегда должна быть возможность быстро подкорректировать действия скрипта - Есть (скрипт составлен достаточно просто; основную часть составляют проверки входных данных)
  • Скрипт не должен накладывать сложные ограничения на ваш код (максимально - необходимость в добавлении функции оповещения о своем выполнении) - Есть (внутри функций getFakeLoader вызывается только функция для оповещения о своем завершении)

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

Современные веб-страницы сильно перегружены файлами 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 кода страницы.

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, что отражается лучшим образом на скорости загрузки ресурсов.

Приветствую, друзья! Знаете ли Вы, что загрузка 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-файлы в один, например, с помощью библиотеки . Пользователям нравятся быстрые сайты 😎