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

Внутри или снаружи?

Давайте в качестве заключения рассмотрим следующий вопрос: стоит ли вообще подключать JavaScript- и CSS-файлы или можно включить весь их код непосредственно в код страницы?

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

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

Многие сайты только наполовину удовлетворяют этим условиям. Для таких случаев в целом лучшим решением будет создание внешних файлов скриптов и таблиц стилей. Единственное исключение, которое можно здесь привести (когда прямое добавление кода дает большое преимущество) — это использование его на главных страницах, таких как главная страница Яндекса ( http://www.yandex.ru/ ), Рамблера ( http://www.rambler.ru/ ) или Google ( http://www.google.ru/ ). Для страниц, которые загружаются всего несколько (обычно — один) раз за весь сеанс, выгодней включать скрипты и таблицы стилей прямо в HTML-документ, чтобы выиграть в скорости загрузки.

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

Глава 5. Параллельные соединения

5.1. Обходим ограничения браузера на число соединений

Активное (англ. keep-alive) соединение стало настоящим прорывом в спецификации HTTP 1.1: оно позволяло использовать уже установленный канал для повторной передачи информации от клиента к серверу и обратно (в HTTP 1.0 соединение закрывалось сразу же после передачи информации от сервера, что добавляло задержки, связанные с трехступенчатой передачей пакетов). В том случае, если проблема свободных ресурсов стоит довольно остро, можно рассмотреть выставление небольшого таймаута для таких соединений (5-10 секунд).
Однако HTTP 1.1 добавил веб-разработчикам головной боли по другому поводу. Давайте будем разбираться, как нам устранить и эту проблему.

Издержки на доставку объектов

Средняя веб-страница содержит более 50 объектов, и издержки на число объектов доминируют над всеми остальными задержками при загрузке большинства веб-страниц. Браузеры, следуя рекомендациям спецификации HTTP 1.1, обычно устанавливают не более 2 одновременных соединений с одним хостом. При увеличении числа HTTP-запросов, требуемых для отображения страницы, с 3 до 23 — время, затрачиваемое именно на «чистую» загрузку объектов, от общего времени загрузки падает с 50% до всего 14%.
Если число объектов на странице превышает 4, то издержки на ожидание доступных потоков и разбор чанков для присланных объектов превалируют над общим временем загрузки страницы (от 80% до 86% для 20 и 23+ объектов соответственно) по сравнению со временем, которое уходит на действительную загрузку данных. Время инициализации плюс время ожидания, вызванное ограничением на параллельные соединения, занимают 50–86% от общего времени загрузки страницы.