Загружаем скрипты без блокировки

advertisement
Загружаем скрипты без блокировки. Loading Scripts Without Blocking от Steve Souders.
Автор рассматривает различные методы загрузки скриптов и выделяет наиболее применимые для
каждого конкретного случая. В основе этой заметки лежит четвертая часть из книги Even Faster
Web Sites, которая является продолжением High Performance Web Sites.
Стыкуем асинхронные скрипты.
Чем больше сайтов вокруг внедряют приложения «Веб 2.0», тем больше становится JavaScript,
загружаемого на страницах этих сайтов. Существует ряд проблем с производительностью таких
страниц, поскольку сами скрипты могут в значительной степени ее ухудшать (например, в IE 6 и
7). Это проявляется в двух возможных блокировках:
− Загрузка остальных ресурсов на странице блокируется до загрузка скрипта,
расположенного выше.
− Блокируется отрисовка элементов страницы (даже если они не требуют никаких внешних
файлов для отображения), расположенные ниже скрипта.
В качестве примера можно привести страницу с 2мя скриптами, за которыми следует картинка,
файл стилей и iframe. По диаграмме загрузки в IE7 прекрасно видно, что первый скрипт блокирует
все нижележащие файлы, а после этого точно так же поступает и второй скрипт, наконец,
картинка, стили и iframe все загружаются параллельно. При загрузке страницы мы сразу видим
параграф текста, расположенный выше скрипта. Однако отображение остального текста в HTMLдокументе блокируется до тех пор, пока не загрузятся все остальные скрипты.
Браузеры однопоточные, поэтому понятно, почему во время выполнения скрипта браузер не
может начать остальные загрузки. Но нет на самом деле никакой причины (Steve немного
перегибает палку: причины есть, и они весьма существенные, в частности, в скрипте может
быть заложено изменение нижележащего DOM-дерева или редирект на другую страницу (от
переводчика)), чтобы блокировать загрузку других компонентов, пока идет загрузка скрипта. И это
именно то, что современные браузеры, включая Internet Explorer 8, Safari 4 и Chrome 2, уже
сделали. Диаграмма загрузки для описанного примера блокировки загрузки в IE8 показывает, что
скрипты загружаются в параллельном режиме, равно как и таблицы стилей. Но картинка и iframe
остаются по-прежнему заблокированными. Safari 4 и Chrome 2 поступают точно так же.
Параллельные загрузки становятся лучше, но все еще далеки от совершенства. Скрипт в iframe.
Оборачиваем скрипт в HTML-страницу и загружаем его как iframe. DOM-элемент для скрипта.
Создаем новый элемент script и назначаем его свойства src равным соответствующему URL. Defer
для скрипта. Добавляем для тега script атрибут defer. Это работало только в IE, но сейчас доступно
и в Firefox 3.1. document.write для скрипта. Вписываем HTML-код <script src=""> прямо на
страницу при помощи document.write. Это загружает скрипты без блокировки только в IE.
Каждый из этих методов можно «пощупать» при помощи Cuzillion. В резульате можно заметить,
что методы достаточно существенно отличаются друг от друга, что приведено в следующей
таблице. Большинство из них обеспечивает параллельную загрузку скриптов, хотя defer и
document.write не везде работают. Также часть описанных приемов не может быть использована
для межсайтовых (cross-site) скриптов, а для некоторых требуется незначительная модификация
текущих скриптов, чтобы заставить их работать в этом режиме. В качестве дополнительных
отличий, которые не так часто упоминаются в обзорах, стоит отметить, затрагивают ли методы
отображение состояния загрузки в браузере (индикатор состояния, индикатор загрузки, иконку
вкладки и курсор мыши). Если вы используете несколько скриптов с частичной зависимостью
друг от друга, вам также потребуется выбрать тот метод, который обеспечивает порядок
выполнения скриптов.
Метод
XHR выполнение
XHR вставка
Скрипт в iframe
DOM-элемент для
скрипта
Defer для скрипта
document.write для
скрипта
IE, FF, Saf, Chr, Op
IE, FF, Saf, Chr, Op
IE, FF, Saf, Chr, Op
Домен
отличие
нет
нет
нет
модифи
Индикаторы
кации
загрузки
нет
Saf, Chr
да
Saf, Chr
нет
IE, FF, Saf, Chr
IE, FF, Saf, Chr, Op
да
да
FF, Saf, Chr
IE, Saf4, Chr2, FF3.1
да
да
IE, FF, Saf, Chr, Op IE, FF, Saf, Chr, Op
~50
IE, Saf4, Chr2, Op
да
да
IE, FF, Saf, Chr, Op IE, FF, Saf, Chr, Op
~100
Параллельность
-
Размер
байт
~500
~500
~50
FF, Op
~200
Сохраняет порядок
И все же: какой из этих методов самый лучший? Ответ на этот вопрос будет зависеть от вашей
конкретной ситуации. Приведенное ниже дерево решения можно использовать как руководство.
На самом деле оно не такое сложное, каким кажется. На принятие решения влияют только три
параметра: расположен ли скрипт на том же домене, что и главная страница; необходимо ли
сохранить порядок выполнения скриптов; и стоит ли вызывать срабатывание индикаторов
загрузки.
В идеале вся логика для этого решения должна быть внедрена в какой-нибудь популярный язык
создания шаблонов HTML-разметки (PHP, Python, Perl и др.) так, чтобы разработчики могли
просто вызвать загрузку скрипта и быть уверенным, что она пойдет по наиболее оптимальному
пути.
В большинстве случаев наилучшим выбором будет создание узла DOM-дерева. Это работает во
всех браузерах, не имеет ограничений на использование доменов, и внедрить так же просто, как
понять механизм передачи (даже Google AutoComplete его использует). Единственная проблема с
этим подходом заключается в том, что он не сохраняет порядок исполнения скриптов (как с этим
бороться, описано в статье Стыкуем асинхронные модули). Если у вас есть несколько скриптов,
которые зависят друг от друга, то вам нужно объединить их все вместе или использовать другой
подход. Если вы используете внутренний код на странице, который зависит от внешнего, то надо
каким-то образом их синхронизовать (один из вариантов такой синхронизации реализован в Web
Optimizer). Я называю такой подход «стыковкой» (coupling) и привел несколько путей для его
реализации в заметке Стыкуем асинхронные скрипты.
Дерево решения для выбора оптимальной техники асинхронной загрузки
Download