Примечание: ниже расположен перевод заметки Positioning Inline Scripts от Steve Souders, в которой он раскрывает тему блокирующих скриптов глубже. Мои комментарии далее курсивом.
В основе этой заметки лежит часть 6 моей книги Even Faster Web Sites, которая является логическим продолжением High Performance Web Sites. В этой серии также доступны следующие заметки: chapters and contributing authors, Splitting the Initial Payload, Загружаем скрипты без блокировки и Стыкуем асинхронные скрипты.
Три предыдущие заметки из Even Faster Web Sites были сфокусированы на внешних скриптах. Но внутренний JavaScript-код на странице блокирует загрузку и отображение так же, как и внешние JavaScript-файлы. Этот пример блокировки JavaScript-кода содержит 2 картинки, между которыми находится часть JavaScript-кода, выполнение которого занимает 5 секунд. Если посмотреть на диаграмму загрузки, то хорошо видно, что загрузка второй картинки (которая расположена сразу за скриптом) блокируется, пока не закончится выполнение скрипта.
Внутренний JavaScript-код блокирует отрисовку страницы даже больше, чем вызовы внешних файлов. Внешние скрипты блокируют только элементы, расположенные ниже их по коду. Тогда как внутренний код блокирует отрисовку всей страницы вне зависимости от расположения элементов. Это можно проиллюстрировать следующим примером. Откройте его в новом окне и отсчитатйе 5 секунд прежде, чем на странице появится хотя бы что-то.
Существует 3 основных стратегии для избежания или в крайней случае смягчения воздействия внутреннего JavaScript-кода на отображение страницы.
setTimeout
для отсрочки долго исполняющегося ода. Если у вас есть функция, выполнение которой занимает большое время, запустите ее через setTimeout
— это позволит отобразить страницы и начать загрузку ресурсов до того, как произойдет блокировка отображения.DEFER
. Это работает в Internet Explorer и Firefox 3.1 или выше. Добавляя атрибут DEFER
к внутренему тегу скрипт SCRIPT
позволит предотвратить блокировку остальных элементов (правда, ничего не написано про блокировку отображения страницы — по всей видимости, это равносильно варианту 1).Steve не упоминает еще одного, вполне логичного пути для избежания таких блокировок, — произведения всех ресурсоемких вычислений на сервере. Браузер может получать уже готовые данные, и получать их в асинхронном режиме, затрагивая процесс отображения страницы по минимуму.
Особенно важно избегать расположения внутренних скриптов между таблицами стилей и любыми другими ресурсами на странице. В этом случае CSS-файл, фактически, заблокирует загрузку всех остальных ресурсов. Причиной этого поведения служит тот факт, что браузеры сохраняют порядок загрузки для CSS и JavaScript. Таблицы стилей должны быть полностью загружены, проанализированы и применены перед выполнением внутреннего скрипта. А внутренний скрипт должен быть выполнен до того, как будут загружены все остальные ресурсы. Таким образом загрузка всех файлов, которые объявлены после таблицы стилей и внутреннего JavaScript-кода будет заблокирована.
Лучше всего данную ситуацию можно раскрыть следующим примером. Ниже расположена диаграмма загрузки для eBay.com. В обычном режиме файл стилей и первый скрипт будут загружаться параллельно. (Оба этих файла находятся на одном домене, поэтому их параллельная загрузка возможна только в браузерах, поддерживающих более двух соединений на один хост, в том числе: Internet Explorer 8, Firefox 3, Safari, Chrome и Opera.). Но после CSS-файла прописан внутренний JavaScript-код (всего одна строчка), который блокирует начало загрузки внешнего скрипта до окончания своего выполнения и получения всего CSS-файла.
Файл стилей, за которым сразу идет внутренний JavaScript-код на eBay.
Аналогичные блокировки также имеют место на MSN, MySpace и Wikipedia. Проблема эта решается переносом внутреннего кода либо перед файлом стилей, либо в самый низ страницы. Это увеличит число параллельных загрузок, что приведет к более быстрой загрузке.