Опубликован: 16.06.2010 | Уровень: специалист | Доступ: платный
Лекция 2:

Обзор методов клиентской оптимизации

< Лекция 1 || Лекция 2: 12345 || Лекция 3 >

1.4.3. Встраивание внешних объектов в код веб-страницы

Встраивание объектов CSS и JS

В ряде случаев фрагменты CSS- и JS-кода, а также изображения можно подставлять напрямую в HTML-документ.

Плюсы такой подстановки очевидны: количество запросов внешних объектов при загрузке страницы уменьшается до минимального количества. Минусом при использовании такого подхода на всех страницах сайта будет то, что пользователь лишится возможности кэшировать какие-либо объекты, вновь и вновь будет загружать их при просмотре страниц сайта.

Из этого очевидно, что подстановку внешних объектов в HTML-документ следует производить в следующих случаях:

  • когда требуется исключительная клиентская производительность страницы, например, на главной странице сайта или других страницах с наивысшей посещаемостью;
  • когда суммарная скорость загрузки всех внешних объектов меньше или приблизительно равняется затратам на поочередный запрос каждого из этих объектов по отдельности, т.е. в ситуациях, когда не возникнет уменьшения скорости загрузки страницы из-за невозможности кэширования внешних объектов;
  • когда требуется полная автономность веб-приложения. Встраивать код CSS следует внутрь тега <style>, расположенного в секции <head> страницы, а JavaScript-код — в теги <script> в конце документа, перед закрывающим тегом <body> либо также внутри секции <head>.

Следуя приведенным выше рекомендациям, необходимо избегать встраивания CSS- и JS-кода непосредственно в теги веб-страницы (т. е. в атрибуты style, onclick и т. д.). Это исключит дублирование кода на странице, а также упростит его сопровождение.

Подстановка изображений

Встраивать изображения прямо в HTML-документ можно, используя схему data:URI. По стандарту RFC 2397 такие URI предназначены для вставки небольших объектов как "непосредственных данных". Синтаксис должен быть следующим:

data:[<тип данных>][;base64],<данные>

В случае изображений необходимо указание mime-типа для них (например, image/gif). После него должно располагаться base64-представ-ление бинарного файла с изображением. Ниже приведен пример такой подстановки:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQA
QMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDr
Az3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkS
uQmCC" width="16" height="14" alt="Встроенное изображение" />

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

У данного подхода есть следующие минусы:

  • изображения в base64-представлении имеют размер примерно на 33% больше исходного;
  • необходимо вычислять и обновлять base64-представление изображения каждый раз, когда оно меняется;
  • требуется отдельное решение для браузера Internet Explorer версии 7 и ниже.

Решение первой проблемы возможно за счет использования gzip-сжатия файлов CSS, в которых располагаются встроенные изображения. Вторая и третья проблемы легко решаются автоматическим преобразованием изображений в base64-представления при помощи серверных скриптов и созданием альтернативной версии кода для указанных браузеров Internet Explorer.

Описание способа автоматического встраивания изображений в код по схеме data:URI можно найти в "Уменьшение количества запросов" .

1.4.4. Исключение избыточных HTTP-запросов

Уменьшение времени разрешения доменного имени

Перед тем как браузер сможет установить соединение с вебсервером, он должен разрешить доменное имя, т. е., зная его, вычислить IP-адрес сервера. Результат может быть закэширован в браузере и операционной системе пользователя, и задержки при повторном открытии веб-страницы не возникнет.


Если же такой записи в кэше не существует, задержка на время поиска IP-адреса может оказаться значительной и будет зависеть от доступности DNS-сервера, содержащего требуемую информацию (а иногда и от доступности цепочки таких серверов).

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

Идеальным с точки зрения минимизации времени разрешения адреса DNS-сервера считается вариант, когда все объекты расположены на том же хосте, откуда была загружена веб-страница. Чем меньше используется хостов, тем больше вероятность того, что браузер сможет повторно использовать уже установленное соединение.

На практике же почти у всех браузеров существуют ограничения на количество одновременных соединений с одним хостом. Принимая во внимание это ограничение, наибольший выигрыш в скорости загрузки страниц можно получить, распределив загружаемые объекты по нескольким (4-6) хостам. Подробнее об особенностях параллельной загрузки объектов можно прочитать в пятой главе книги "Разгони свой сайт".

Уменьшение количества редиректов

Иногда возникает необходимость перенаправить браузер с одного адреса на другой. Причины чаще всего следующие:

  • добавить косую черту к имени домена;
  • предоставить пользователю документ, перемещенный на другой адрес;I позволить пользователю обращаться к документам сайта даже если он ошибся в написании адреса (например, не набрал www в начале адреса);
  • направить пользователя на другие домены первого уровня, основываясь на его географическом месторасположении и данных об используемом им языке;
  • направить пользователя на определенные страницы в зависимости от того, авторизован он или нет;
  • направить пользователя на страницы с другим протоколом (HTTP или HTTPS);
  • отследить и сохранить действия пользователя и т. д.

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

  • следить за тем, чтобы ссылки на веб-страницах не вели на адреса, где заведомо будет срабатывать редирект;
  • избегать цепных (последовательных) редиректов;
  • использовать минимальное количество альтернативных адресов для одних и тех же страниц, стараясь предоставить всем пользователям единственный актуальный адрес для каждой страницы;
  • использовать внутренние перенаправления — функцию, доступную в большинстве веб-серверов;
  • использовать средства отслеживания информации о пользователе, не основанные на редиректах;
  • предпочитать серверные редиректы клиентским, которые могут быть заданы при помощи тега <meta> или JavaScript-обработчика. Редиректы, отправляющие браузеру код состояния 300, 301 или 302 и заголовок Location, обрабатываются браузером моментально, а при выполнении клиентских редиректов браузеру требуется дополнительное время на разбор полученной веб-страницы. Кроме того, некоторые браузеры могут кэшировать информацию о ре-директах, тем самым ускоряя повторную загрузку ранее открытых веб-страниц.

1.4.5. Настройка кэширования

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

Кэширование — это один из наиболее мощных механизмов для уменьшения объема передаваемых по сети данных, притом внедряется этот механизм очень просто. Ниже приведено краткое описание наиболее значимых для кэширования заголовков.

Заголовок Expires

Когда HTTP-сервер отправляет объект (например, HTML-документ или изображение) браузеру, он может дополнительно с ответом отправить заголовок Expires с меткой времени. Браузеры обычно хранят ресурс вместе с информацией об истечении его срока действия в локальном кэше. При последующих запросах к тому же объекту браузер сравнивает текущее время и метку времени у находящегося в кэше ресурса. Если метка времени указывает на дату в будущем, браузер загружает ресурс из кэша, не запрашивая его с сервера. Формат должен быть строго следующим:

день недели(сокр.), число(2 цифры) месяц(сокр.) год часы:минуты:секунды GMT

Заголовок Expires устанавливает время актуальности информации. Для ресурсов, которые не должны кэшироваться, его нужно выставлять в текущие время и дату (документ устаревает сразу же после получения), для форсирования кэширования его можно определять на достаточно далекую дату в будущем, например:

Expires: Mon, 27 Dec 2027 00:00:00 GMT
Заголовок Cache-Control

Заголовок Cache-Control определяет набор директив, относящихся непосредственно ко времени и специфике кэширования документа. Для запрета кэширования можно выставить его в следующее значение:

Cache-Control: no-store, no-cache, must-revalidate

Если же, наоборот, требуется сохранить ресурс в кэш браузера на продолжительный период времени, например, на год (60 * 60 * 24 * 365 секунд), нужно отправлять следующий заголовок:

Cache-Control: max-age=31536000
Заголовки Last-Modified, If-Modified-Since

Заголовок Last-Modified может отправляться сервером для того, чтобы передать браузеру информацию о дате последнего изменения документа. Дата должна задаваться в том же формате, что и в случае с заголовком Expires:

Last-Modified: Tue, 4 Aug 1995 04:58:08 GMT

При наличии такой информации в локальном кэше браузер может в следующем запросе отправить ее в заголовке If-Modified-Since:

If-Modified-Since: Tue, 29 Oct 1994 19:43:31 GMT

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

Данная схема позволяет экономить время, затрачиваемое на передачу данных, однако при ее использовании браузер все равно будет устанавливать соединение с сервером, чтобы узнать, имеется ли более новая версия.

Заголовки ETag, If-None-Match

Заголовок ETag является почти полной аналогией заголовка Last-Modified за тем исключением, что в качестве передаваемого значения может выступать произвольная строка. Заголовок отправляется сервером в следующем формате:

ETag: "any-type-of-tag-or-hash"

Впоследствии, для того чтобы сервер мог определить, является ли объект, находящийся в кэше браузера, точно таким же, как соответствующий объект на сервере, браузер может отправить следующий заголовок:

If-None-Match: "any-type-of-tag-or-hash"

И аналогично, если теги совпадают, сервер отвечает кодом состояния 304 Not Modified и данные не передаются повторно. В противном случае сервер передаст новую версию файла.

Форсированный сброс кэша

Если время кэширования при помощи заголовков Expires и Cache-Control установлено на несколько лет вперед и требуется сообщить клиентскомубраузеру, что исходный объект изменился, можно воспользоваться двумя способами.

Можно обновить GET-строку запроса, например, используя номер версии или дату последнего изменения:

http://testdomain.com/global.css?v1

http://testdomain.com/global.css?20080901

А можно добавить номер версии или дату последнего изменения в само имя файла:

http://testdomain.com/global.v1.css

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

В спецификации RFC-2616 HTTP-кэшированию посвящена целая глава. В ней подробно рассматривается, как работают все приведенные выше заголовки. Также о многих тонкостях использования кэширования более подробно рассказано в "Уменьшение количества запросов" .

< Лекция 1 || Лекция 2: 12345 || Лекция 3 >
Ольга Артёмова
Ольга Артёмова

Доброго времени суток!

Прошла курс, но почему-то диплом получить не могу, хотя курс значится завершенным, хотя обязательные два модуля пройдены. Как решить эту проблему?

Сертификация: оптимизация и продвижение web-сайтов.

Ярославй Грива
Ярославй Грива
Россия, г. Санкт-Петербург
Ёдгор Латипов
Ёдгор Латипов
Таджикистан, Кургантепа