# серверной производительностью, следует уменьшить до 7 или 1)
DeflateCompressionLevel 9
# и максимальный размер окна для архивирования
DeflateWindowSize 15
# отключаем архивирование для «проблемных» браузеров
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
# добавляем заголовок Vary для корректного распознавания браузеров,
# находящихся за локальными прокси-серверами
Header append Vary User-Agent
# и запрещаем кэширование сжатых файлов для локальных прокси-серверов
Header append Cache-Control private
Полные оптимизированные конфигурации для указанных серверов приведены в восьмой главе.
2.2. CSS и JavaScript в виде архивов
Теперь давайте рассмотрим, каким образом лучше всего будет отдавать CSS- и JavaScript-файлы в архивированном виде. Для обеспечения корректного архивирования, по-видимому, наиболее общий подход будет заключаться в выполнении по порядку следующих пунктов:
проверить, умеет ли клиент принимать файлы в формате gzip-encoded;
обеспечить соответствующий вывод на стороне сервера через gzip-функции либо организовать это непосредственно через веб-сервер (например, Apache);
настроить конфигурационные файлы (или .htaccess), чтобы обеспечить корректный Content-Type.
В данном случае сжатие данных «на лету», возможно, не будет наиболее оптимальным решением, потому что файлы стилей и скриптов изменяются достаточно редко, а мы заставим сервер каждый раз их сжимать. Тем более что лучше самого сервера с архивацией файлов никто не справится.
Статическое архивирование в действии
Есть способ обойтись просто парой строчек в конфигурационном файле (httpd.conf или .htaccess, первое предпочтительнее), если потратить пару минут и самостоятельно заархивировать все необходимые файлы. Предположим, что у нас есть JavaScript-библиотека jquery.js на сервере. Заархивируем ее в jquery.js.gz (при помощи 7-zip или любой другой утилиты, если в работе используется Windows). В итоге, должен появиться файл jquery.js.gz. Его нужно положить в ту же директорию на сервере, что и исходный файл.
Если работать прямо на сервере через командную строку, то достаточно выполнить следующую команду:
gzip jquery.js -c –n -9 > jquery.js.gz
Опция –c создаст новый файл (перенаправляем поток вывода в jquery.js.gz), -n исключит имя файла из архива (оно там только лишние байты занимает), а -9 заставит использовать максимальную степень сжатия. Таким образом, мы получим минимально возможный архив из искомого файла.
Проблемы для Safari
В ходе реализации данного решения возникла маленькая, но досадная неприятность. Safari не умеет правильно обрабатывать файлы с расширением .gz: для этого браузера стили и скрипты не могут иметь такого расширения. Как же нам быть? Выход достаточно простой и очевидный.
Нам нужно именовать все архивы стандартным образом, но при этом иметь неархивированную версию для обратной совместимости (например, с дополнительным суффиксом nogzip). Поэтому для подготовки файлов нам будут нужны две команды (jquery здесь используется только в качестве примера):
cp $src/jquery.js $dst/jquery.nogzip.js
gzip $dst/jquery.nogzip.js -9 –n -c > $dst/jquery.js
где $src — директория, в которой хранятся исходные файлы, а $dst — финальная директория для публикации. Сначала мы копируем файл в финальное место дислокации, а потом его архивируем под «правильным» именем.
Конфигурируем Apache
Тесты под Konqueror показали, что этот браузер не понимает архивированных файлов (CSS и JavaScript), поэтому чтобы уберечь десятую долю процента посетителей от сердечного приступа (когда они увидят сайт без соответствующих стилей), стоит добавить его в этот набор правил. Аналогично и «старым» браузерам (которые явно указывают, что не понимают архивов) отдается неархивированное содержание.
RewriteEngine On
# перенаправляем Konqueror и «старые браузеры»
RewriteCond %{HTTP:Accept-encoding} !gzip [OR]
RewriteCond %{HTTP_USER_AGENT} Konqueror
RewriteRule ^(.*)\.(css|js)$ $1.nogzip.$2 [QSA,L]
Вся вышеуказанная конструкция «обернута» условием наличия на сервере подключенного mod_rewrite. Если он отсутствует, то это сразу станет видно на заявленных браузерах (перестанут отображаться стили и отрабатывать скрипты). Иначе Apache просто не сможет запуститься, т. к. RewriteEngine не будет объявлен.
Дополнительно к заявленной логике необходимо выставить ряд заголовков для отдаваемых файлов. В частности, Vary и Cache-control касаются локальных проксирующих серверов, которые не должны кэшировать эти файлы, а пропускать их дальше к пользователю, не обрезая при этом заголовок User-Agent (иначе наш сервер никак не узнает, можно ли отдавать архивированную копию файла или нет).
Header append Vary User-Agent
# выставляем для всех css/js файлов Content-Encoding
Header set Content-Encoding: gzip
Header set Cache-control: private
# сбрасываем Content-Encoding в том случае, если отдаем не архив
Header unset Content-Encoding