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

Поводом к написанию этого поста послужило то, что не раз мне приходилось замечать, что вставка на страницу кода кнопок различных сервисов (например: вконтакте, фейсбук, твиттер, одноклассники) приводила к заметному замедлению загрузки и отображения страницы. Речь идет о том случае, когда используется подключение внешних javascript этих социальный сервисов.
Если мы используем простые статичные графические кнопки, никаких проблем нет, т.к. это минимум графики и скриптов, которые расположены локально (можно посмотреть пример реализации тут http://pervushin.com/social-button-for-blog.html). Но мы видим только иконки соц. сервисов, никакой статистики (сколько нашу страницу "залайкнули") нет. Т.е. если мы хотим видеть и статистику, то придется подключать внешние скрипты. И тут стоит иметь в виду, что сколько таких кнопок мы подключили, то столько внешних скриптов браузер вынужден скачать, т.е. это дополнительные подключения к внешним серверам.

Чтобы показать, что происходит, если на странице есть скрипты в секции , предлагаю рассмотреть ряд тестовых примеров. Я буду использовать FireFox 3.6 и FireBug.

Итак:
1) Простейшая страница с одним файлом стилей, двумя скриптами и тремя картинками:













А вот диаграмма загрузки для нее:

Обратите внимание, что все картинки грузятся только после загрузки самого "долгого" javascript файла.
Я намеренно сделал довольно длительной загрузку dummy_css.css и dummy_js.js. Это просто два файла:

dummy_css.php

html, body {
margin:0;
padding:0;
}
.img_container{
margin:0 auto;width:500px;
}

dummy_js.php


var param=1;

Итак, видно что js файл блокирует загрузку всей остальной графики.

2) Все почти то же самое, но dummy_ js. js грузится с внешнего хоста:

Ситуация аналогична предыдущей:

3) Попробуем поменять в секции head местами css и js файлы (css теперь идет после js):







Смотрим на диаграмму загрузки:

Js по-прежнему блокирует загрузку картинок, независимо от того, с какого хоста он грузится.

4) Увеличим по времени загрузку css до 4-х секунд (html код как в случае N3):

5) Еще один интересный случай: css располагается до js, но css грузится дольше















Тут уже css блокирует загрузку картинок...

6) Переносим один js внутрь < body>
















Видно, что dummy_ js. js блокирует загрузку только третьей картинки, которая расположена в html коде после него. Но если css грузится дольше, то тогда уже он будет блокировать загрузку графики. Нетрудно представить, что подключаемые внешние скрипты могут сильно замедлить загрузку и отрисовку страницы, особенно если удаленный сервер по каким-то причинам долго отвечает.

Размещение внешних скриптов перед

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

Но есть еще одна проблема, поясню на примере:




$("img").click(function() {
alert($(this).attr("src"));
});
});






Если js перед будет грузиться долго, то клики по картинкам до полной загрузки этого скрипта ни к чему не приведут, т.к. $(document).ready() сработает только после полной загрузки js. Так что если на страницах есть некая логика, которая предусматривает обработку событий, то этот способ мало подходит.

Итак, что нужен способ неблокирующей загрузки скриптов...

Создаем async.js:



script.src = "dummy_js.js";


и подключим его:











$(document).ready(function() {
$("img").click(function() {
alert($(this).attr("src"));
});
});






Если вызов async.js разместить в ,а не перед , то диаграмма получится такая:

Но если в коде все-таки удобнее размещать async.js именно в , то следует немного поменять содержимое async.js:

$(document).ready(function() {
var script = document.createElement("script");
script.src = "dummy_js.js";
document.getElementsByTagName("head") .appendChild(script);
}
);

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

) я писала о том, какой эффект оказывают JavaScript-файлы на Критический Путь Рендеринга(CRP).


JavaScript является блокирующим ресурсом для парсера. Это означает, что JavaScript блокирует разбор самого HTML-документа. Когда парсер доходит до тега <script> (не важно внутренний он или внешний), он останавливается, забирает файл (если он внешний) и запускает его.

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


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

Нормальное выполнение

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


... ... ....

Вот что произойдёт, когда парсер будет обрабатывать документ:

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

Атрибут async

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



Атрибут доступен только для файлов, подключающихся внешне. Если внешний файл имеет этот атрибут, то он может быть загружен в то время как HTML-документ ещё парсится. Парсер будет приостановлен для выполнения скрипта, как только файл скрипта будет загружен.



Атрибут defer

Атрибут defer указывает браузеру, что скрипт должен быть выполнен после того, как HTML-документ будет полностью разобран.



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



Асинхронное, отложенное или нормальное выполнение?

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

Где расположен элемент ?

Асинхронное и отложенное выполнения наиболее важны, когда элемент не находится в самом конце документа. HTML-документы парсятся по порядку, с открытия до его закрытия. Если внешний JavaScript-файл размещается непосредственно перед закрывающим тегом , то использование async и defer становится менее уместным, так как парсер к тому времени уже разберёт большую часть документа, и JavaScript-файлы уже не будут оказывать воздействие на него.

Скрипт самодостаточен?

Для файлов, которые не зависят от других файлов и/или не имеют никаких зависимостей, атрибут async будет наиболее полезен. Поскольку нам не важно, когда файл будет исполнен, асинхронная загрузка - наиболее подходящий вариант.

Полагается ли скрипт на полностью разобранный DOM?

Во многих случаях файл скрипта содержит функции, взаимодействующие с DOM. Или, возможно, существует зависимость от другого файла на странице. В таких случаях DOM должен быть полностью разобран, прежде чем скрипт будет выполнен. Как правило, такой файл помещается в низ страницы, чтобы убедиться, что для его работы всё было разобрано. Однако, в ситуации, когда по каким-либо причинам файл должен быть размещён в другом месте - атрибут defer может быть полезен.

Скрипт небольшой и зависим?

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

Поддержка и современные браузерные движки

Поддержка атрибутов async и defer очень распространена:




Стоит отметить, что поведение этих атрибутов может немного отличаться в разных движках JavaScript. Например, в V8 (используется в Chromium), сделана попытка разобрать все скрипты, независимо от их атрибутов, на отдельном выделенном потоке для выполнения скрипта. Таким образом, «блокирующая парсер» природа JavaScript-файлов должна быть минимизирована по умолчанию.

С ростом скорости интернет соединения и увеличении мощности не только десктопных, но и мобильных устройств веб страницы стают более "тяжелыми". Количество и размер подключаемых файлов растет: JavaScript файлы, css файлы, изображения, виджеты сторонних сайтов, iframe. На данный момент специфика работы браузеров такая, что при загрузке js файла блокируется отривсовка до того момента, пока скрипт не выполниться. Современные браузеры в фоновом режиме будут парсить документ и скачивать скрипты и стили, но отрисовка будет заблокирована. Сравнение сетевых параметров для различных браузеров можно посмотреть на browserscope.org . Мы не можем устранить блокировку полностью, но можем оптимизировать серверную и клиентскую часть приложения, что бы блокировка отрисовки занимала наименьший промежуток времени.

Решения для серверной части:
- Уменьшить размер передаваемых файлов
- Использовать CDN
- Вынести статические файлы на отдельный домен или под домен, таким образом увеличить количество одновременных соединений браузера.
- Включить сжатие передаваемых файлов(gzip)

Решения для клиентской части:
- Уменьшить количество запросов.
- Кэшировать файлы на стороне клиента с помощью заголовков Expires и Etags.
- Использовать общедоступные CDN(Google CDN, Yandex CDN). Таким образом, существует вероятность, что файл с общедоступного CDN уже будет храниться в кеше браузера.

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

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

(function() { var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = "URL файла"; document.getElementsByTagName("head").appendChild(script); })();

Если JavaScript нужно выполнить после загрузки всей страницы, включая содержание, изображения, стилевые файлы и внешние скрипты, то к загрузчику нужно добавить отслеживания события onload.

If (window.addEventListener) { window.addEventListener("load", async_load, false); } else if (window.attachEvent) { window.attachEvent("onload", async_load); }

Скрипт асинхронной загрузки JavaScript с учетом события onload (function() { function async_load(){ var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = "URL файла"; document.getElementsByTagName("head").appendChild(script); } if (window.addEventListener) { window.addEventListener("load", async_load, false); } else if (window.attachEvent) { window.attachEvent("onload", async_load); } })();

Но это единичный случай, когда требуется загрузка одного файла. Часто на практике подключается множество файлов.

Скрипт асинхронной загрузки множества подключаемых JavaScript файлов (function() { function async_load(){ [ "URL_файла_1.js", "URL_файла_2.js", "URL_файла_3.js" ].forEach(function(src) { var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = src; document.getElementsByTagName("head").appendChild(script); }); } if (window.addEventListener) { window.addEventListener("load", async_load, false); } else if (window.attachEvent) { window.attachEvent("onload", async_load); } })();

Но в такой реализации есть минус - скрипты будут загружаться в произвольном порядке и соответсвенно выполнятся они будут произвольно во времени. Данный скрипт асинхронной загрузки идеально подходит, если выполнение JavaScript файлов не зависят один от другого и не зависит от DOM. В обратном случае его использование может привести к ошибкам на странице или непредвиденному результату выполнения. Для последовательного выполнения, но асинхронной загрузки, нужно указать async=false, тогда файлы будут скачиваться в произвольном порядке, но выполняться по очереди.

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

Стандарт HTML 5 поддерживает асинхронную загрузку JavaScript. Это можно сделать путем добавления ключевого слова async или defer. Например:

Скрипт, который подключен с атрибутом defer выполнится не нарушая порядок выполнения по отношению к остальным скриптам и его выполнение произойдет после полной загрузки и парсинга страницы, но перед тем, как вызовется DOMContentLoaded.

Скрипт, который подключен с атрибутом async выполнится при первой возможности после полной загрузки, но при этом не ожидает окончания парсинга документа и до загрузки объекта window. Браузеры не гарантируют выполнение скриптов в том же порядке в котором они подключены.

Библиотеки для асинхронной загрузки JavaScript

RequireJS - модуль загрузки JavaScript. Оптимизирован под браузеры, но он может использоваться в других средах, таких как Node, Rhino.

Require(["script"], function(script) { console.log("start after load script.js"); });

extsrc.js - библиотека, которая запускает скрипты на выполнение после того, как страница загрузится и отобразится пользователю. Работает корректно с document.write.

yepnope.js - позволяет совершать асинхронную загрузку JavaScript и CSS файлов.

Yepnope([ "script.js", "style.css" ]);

Простой способ загрузки JavaScript скриптов

Оказывается, что на практике добиться оптимальной кросс браузерной загрузки JavaScript скриптов, которые не блокируют отображение сложно, а порой невозможно. Наиболее оптимальный способом является добавление в конец документа перед закрывающимся тегом body. Из за ограничения разных браузеров и самого HTML такой вариант загрузки, который не блокирует отображение, можно считать наиболее простой.

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

Примечание: ниже расположен перевод статьи от 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). Пример такого поведения расположен на странице с



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

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

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