


Шаблон двойного скрипта от John Resig. Стыкуем асинхронные скрипты. Оптимизация структуры веб-страниц
Асинхронная загрузка скриптов
Шаблон двойного скрипта от John Resig
«Ленивая» загрузка
Заключение
Асинхронная загрузка скриптов позволяет укорить загрузку страницы, но в этом случае остается, что улучшить. По умолчанию скрипт вызывает «сам себя» при помощи прикрепления sorttable.init() к обработчику события onload для этого скрипта. Некоторое улучшение производительности (и уменьшение кода) может быть достигнуто, если вызвать sorttable.init() внутри тега script, чтобы вызвать его сразу же после загрузки внешнего скрипта (подключенного через src).
Выше описано три способа по стыковке внутреннего кода с асинхронной загрузкой внешних скриптов: window onload, onreadystatechange у скрипта и встроенный в скрипт обработчик. Вместо всего этого можно использовать технику от John Resig - шаблон двойного тега script. John описывает, как связать внутренние скрипты с загрузкой внешнего файла следующим образом:
<script src="jquery.js" type="text/javascript">
jQuery("p").addClass("pretty");
</script>
В этом случае код внутри <script> срабатывает только после того, как загрузка и инициализация внешнего скрипта завершилась. У этого подхода по стыковке скриптов есть несколько очевидных преимуществ: проще: один тег script вместо двух прозрачнее: связь внутреннего и внешнего кода более очевидная безопаснее: если внешний скрипт не загрузится, внутренний код не будет выполнен, что предотвратит появление ошибок, связанных с неопределенными переменными
Это замечательный шаблон для асинхронной загрузки внешних скриптов. Однако чтобы его использовать нам придется внести изменения как во внутренний код, так и во внешний файл. Для внутреннего кода придется добавить уже упомянутую выше третью строку, которая выставляет свойство script.text. Для завершения процесса стыковки нужно добавить в конец sorttable-async.js:
var scripts = document.getElementsByTagName("script");
var cntr = scripts.length;
while ( cntr ) {
var curScript = scripts[cntr-1];
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);
Этот подход был уже описан в книге «Разгони свой сайт» (http://speedupyourwebsite.ru/books/speed-up-your-website/ ), однако, он предполагает дополнительную нагрузку на процессор для постоянной проверки готовности искомого скрипта и не срабатывает в случае недоступности внешнего файла: проверка продолжает выполняться.
Однако в случае проверки по интервалу нам совсем не нужно модифицировать внешний файл, в случае же двойного использования тега script это просто необходимо. Проверку по интервалу можно улучшить, если по истечению некоторого времени (5-10 секунд, например) перезапускать загрузку внешнего файла (меняя исходный тег script при помощи уникального GET-параметра), а после нескольких неудачных перезапусков вообще прекращать загрузку (возможно, с каким-то сообщением об ошибке).