08.04.2009

Дилемма о загрузке JS-файлов

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

<div id="something">
    ...
</div>
<script>
    Something.init();
</script>

Понятно зачем — чтобы свести к минимуму задержку между двумя событиями: 1) HTML компонента отобразился и 2) JS компонента загрузился и инициализировался.

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

Разумеется, для этого нужно грузить JS-код компонента вперед HTML-кода (обычно это делают в <head>).

***

С другой стороны, следуя рекомендациям ведущих специалистов по борьбе с тормознутостью сайтов, хочется вынести загрузку всех JS-файлов в конец страницы (перед закрывающим тегом <body>).

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

Однако, минус очевиден — увеличивается задержка между рассмотренными выше событиями 1) и 2). То есть мы получаем, что пользователь дольше видит HTML с еще не наложенным яваскриптом.

***

Что делать? Я думаю, что правильный путь — это все-таки вынести загрузку всех JS-файлов в конец страницы, при этом в <head> грузить один маленький легковесный скрипт, который при попытке пользователя взаимодействовать с компонентом при еще не наложенном JS, будет сигнализировать ему, что, мол, все окей, подожди чуть-чуть, JS грузится и скоро наступит счастье.

Вот и Мэтт Снайдер похожим путем идет. А как вы решаете эту дилемму?

8 комментариев:

alpha комментирует...

Я на такие элементы навешиваю css-класс, который при включенном js на странице, для тех компонент, которым необходим js, делает visibility: hidden. А когда js компонента инициализируется, он убирает этот css-класс.

Этот подход похож на указание атрибутов width и height для image, когда место под изображение резервируется браузером сразу.

Unknown комментирует...

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

Анонимный комментирует...

minify наше все. Один css-файл, один js-файл, и все это кешируем.

alpha комментирует...

Минимизация лишь уменьшает проблему, но уж точно не решает.

Анонимный комментирует...

Проблема

>> Понятно зачем — чтобы свести к минимуму задержку между двумя событиями: 1) HTML компонента отобразился и 2) JS компонента загрузился и инициализировался.

как раз таки и решается. А написание дополнительного кода в попытке скрыть собственное неумение кратко и понятно писать - это плохо...

alpha комментирует...

Если было кода 100 КБ, разбросанного по 10 файлам, а после минимизации стало 50 КБ в одном, это конечно уменьшит время, когда пользователь видит неинициализированный компонент. Но проблема в том, что он все равно его видит, пусть и меньшее количество времени.

Александр Улизько комментирует...

В случае, если весь js, что есть на сайте - только какая-нибудь интерактивная форма связи + slideshow, то вставялю script в конец body и не парюсь.

minify + gzip + cache позволяет небольшие файлы выплевывать практически мгновенно.



А в случае веб-приложений, где несжатого js кода порядка 600-700 килобайт, я показываю прелоадер до тех пор, пока весь необходимый для работы js не подгрузится (примерно как в gmail).

И, кстати, в этом случае я не гружу на каждую страницу весь js что есть, пусть даже это и плохо с точки зрения кеширования, js подгружается только по мере необходимости - и трафик бережется, и движок память лишним функционалом не забита.

Unknown комментирует...

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