Выбрать главу

Финальная конструкция выглядит примерно следующим образом:

<link type="text/css" rel="stylesheet" href="main.css" media="screen" />

<!-—[if lt IE 7]><link type="text/css" rel="stylesheet"

href="ie6.css" media="screen" /><!endif-->

Для всех браузеров используется main.css, а для IE6 и ниже — ie6.css. Однако Internet Explorer этих версий не запрашивает файлы стилей параллельно, поэтому при загрузке страницы произойдет ненужная задержка, связанная с доставкой еще одного файла.

Чтобы избежать ее (особенно в случае небольшого количества стилей конкретно для IE), можно использовать CSS-хаки уже в исходном CSS-файле. Например, если нам нужно определить правило только для IE7, мы можем написать так:

*+html body {

margin: 0 auto;

}

для IE6:

* html body {

margin: 0 auto;

}

и для IE5.5- (эта группа браузеров не распознает экранирование символов, поэтому сможет применить только первое правило из двух, второе правило отработает для IE6, переопределив первое):

* html body {

margin: 0;

marg\in: 0 auto;

}

CSS-хаки позволяют совершенно свободно использовать всего один файл стилей для гарантии кроссбраузерности верстки. При этом производительность страницы будет максимальной (исключая, конечно, случай включения всех CSS-правил в исходный HTML-документ — это будет работать еще быстрее, однако чревато некоторыми сложностями; подробнее о них в конце этой главы).

4.2. Объединение JavaScript-файлов

Все внешние JavaScript-файлы с сайта можно слить в один большой, загружаемый только один раз и навсегда. Это очень удобно: браузер не делает тысячу запросов на сервер для отображения одной страницы, скорость загрузки резко повышается. А пользователи так же счастливы, как и разработчики.
Как всегда, в бочке меда есть ложка дегтя: в объединенный файл попадает много того, что при первом запросе можно было бы и не загружать. Чаще всего для борьбы с этим предлагают ненужные части убирать вручную. Однако каждый раз делать одни и те же операции после изменения модулей очень надоедает. Ниже приведено описание простейшего алгоритма разрешения этой проблемы путем описания зависимостей между модулями.

Конструктивные предложения

Для начала стоит разобрать используемый фреймворк на составные части. JSON — отдельно, AJAX — отдельно, работа с DOM — отдельно, формы — отдельно. После этого задача «выкидывания ненужного» превращается в задачу «собери только нужное». Несомненный плюс — результат сборки стал гораздо меньше. Несомненный минус — если что-то из «нужного» забыто, все перестает работать.
Информацию о зависимостях между составными частями можно хранить в удобном для автоматического использования виде. (Формы используют функции DOM, JSON — AJAX и так далее.) На этом шаге забыть что-то нужное становится заметно труднее, а сборка превращается из увлекательной головоломки в рутинную и автоматизируемую операцию.
Также можно хранить информацию о том, какие именно модули нужны сайту в целом. Используется ли AJAX? Если ли формы? Может быть, какие-то необычные элементы управления?
Да, естественно, все это можно и нужно автоматизировать.

В теории

С формальной точки зрения, после того как первые два предложения воплощены в жизнь, у нас появляется дерево зависимостей. Например, такое:

— dom.js

— array.map.js

— array.js

— sprinf.js

— calendar.js

— date.js

— mycoolcombobox.js

— dom.js

— array.map.js

— array.js

— sprinf.js

— animated.pane.js

— pane.js

— dom.js

— array.map.js

— array.js

— sprinf.js

— animation.js

— transition.js

... и так далее ...

Дальше мы выбираем непосредственно нужные сайту вершины. Пусть это будут dom.js и animated.pane.js. Теперь это дело техники — обойти получившийся набор деревьев в глубину:

— array.js

— array.map.js

— sprinf.js

— dom.js

— array.js

— array.map.js

— sprinf.js

— dom.js

— pane.js

— transition.js

— animation.js

— animated.pane.js

...удалить повторяющиеся элементы:

— array.js

— array.map.js

— sprinf.js

— dom.js

— pane.js

— transition.js

— animation.js

— animated.pane.js

и слить соответствующие модули воедино.

На практике

Хранить информацию о зависимостях можно, например, следующим образом (добавляя в «модули» служебные комментарии):

// #REQUIRE: array.map.js

// #REQUIRE: sprintf.js

....

код

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

К чему мы пришли?

Затратив один раз кучу времени на формирование модулей и зависимостей между ними, мы экономим время каждый раз, когда хотим уменьшить объем загружаемого клиентов внешнего файла. Это приятно. Но все-таки часть проблемы осталась — пользователь загружает весь JavaScript-код, который используется на сайте в течение первого захода на произвольную страницу, даже если на текущей странице этот код не нужен.