|
Примечание: ниже частичный перевод статьи
"Compress JavaScript and CSS without touching your application code", в
которой описывается статичное сжатие CSS- и JS-файлов на сервере и корректная
выдача их затем клиенту. Далее даны мои комментарии с более комплексным
решением. Приношу извинения, если для кого-то тема будет слишком знакома или
неинтересна: в Рунете нормальной статьи на данную конкретную тематику обнаружить
не удалось.
Для обеспечения корректного архивирования вашего веб-контента, по-видимому,
наиболее общий подход будет заключаться в выполнении по порядку следующих
пунктов:
- Проверить, умеет ли клиент принимать файлы в формате gzip-encoded.
- Обеспечить соответствующий вывод на стороне сервера через gzip-функции,
либо уповать на то, что всем этим займется непосредственно Apache.
- Поиграться с
.htaccess, чтобы обеспечить корректный
content type.
Проблема заключается в том, что все эти шаги вам придется выполнить
самостоятельно. Сжатие данных «на лету», возможно, не будет наиболее оптимальным
решением, тем более, что я не являюсь фанатом архивации файлов в серверных
приложениях — этим должен заниматься сам сервер.
Однако, существует способ обойтись просто парой строчек в конфиге (.htaccess),
если потратить пару минут и самому заархивировать все необходимые файлы.
Предположим, что у нас есть JS-библиотека prototype.js на сервере.
Заархивируйте ее через gzip (при помощи 7-zip или еще чего-нибудь, если вы
работаете под Windows). В итоге, у вас должен появиться файл prototype.js.gz.
Поожите его в ту же директорию на сервере, что и исходный файл. Если вы
работаете через командную строку в шеле, то достаточно выполнить:
gzip foo.js -c > foo.js.gz
Теперь добавим следующие строки в .htaccess в корень вашего сайта (прим.
лично я бы рекомендовал записать прямо в конфиге апача). При этом нужно
будет включить RewriteEngine, если он еще не подключен:
AddEncoding gzip .gz
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{HTTP_USER_AGENT} !Safari
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*)$ $1.gz [QSA,L]
В первой строке мы сообщаем серверу, что файлы с расширением .gz
нужно отдавать с gzip encoding-type, чтобы браузер понял, что перед ним
архив, а текстовый файл. Второй строкой проверяется, принимает ли браузер
архивированные файлы, при этом следующие строки просто не отработают, если этот
тест провалится. Далее мы исключаем Safari, у которого проблемы с правильным
восприятием архивированного содержимого. На четвертой строке мы проверяем, что
архивный файл существует, и если это так, то добавляем .gz к
существующему имени файла.
С такой конфигурацией вы можете загружать сжатые версии ваших файлов на
сервер и Apache сможет отдавать их заместо обычных, если сможет это сделать, при
этом вам не придется менять теги <script> или любые вызовы в веб-приложениях.
Примечание: далее идут мои рассуждения на тему и собственное решение.
Во-первых, тесты под некоторыми Konqueror'ами показали, что он тоже не
понимает заархивированных файлов (CSS- и JS-), поэтому ради безопасности десятых
долей процента посетителей от сердечного приступа (когда они увидят сайт без
соответствующих стилей) в этот набор правил его стоит добавить.
Во-вторых, мне не нравится, что при каждом запросе (ну или при 99%) к
статичному ресурсу, Apache должен что-то искать и менять физический адрес, по
которому этот файл нужно брать. Я против таких решений, поэтому я предложу
другой путь: давайте будем переопределять физический адрес ресурса только для
«старых» браузеров, а для всех остальных отдавать рядовой файл.
RewriteEngine On
AddEncoding gzip .gz
RewriteCond %{HTTP:Accept-encoding} !gzip [OR]
RewriteCond %{HTTP_USER_AGENT} Safari [OR]
RewriteCond %{HTTP_USER_AGENT} Konqueror
RewriteRule ^(.*).gz(?.+)?$ $1 [QSA,L]
<FilesMatch .*.js.gz$>
ForceType text/javascript
Header set Content-Encoding: gzip
</FilesMatch>
<FilesMatch .*.css.gz$>
ForceType text/css
Header set Content-Encoding: gzip
</FilesMatch>
В итоге, логика «переворачивается», и вместо набора «И»-условий мы получаем
«ИЛИ»-условия. Первые пять строк уже достаточно подробно обсуждены вверху, я
только остановлюсь на последней из них
RewriteRule ^(.*).gz(?.+)?$ $1 [QSA,L]
В ней учитывается, что к статичным ресурсам можно добавлять уникальные
GET-строки, чтобы перегружать кеш на клиенте (если ресурс поменялся, то стоит
обновить его в кеше, иначе клиенты увидят старую версию). Например,
foo.css.gz?v1234.
Следующие строки (ForceType / set Content-Encoding) форсируют для
скриптов и файлов стилей соответствующие MIME-типы и Content-Encoding (ибо как
удалось нарыть
здесь, так браузеры воспринимают ответ лучше). Единственное неудобство,
которое может возникнуть — придется поменять все вызовы JS-/CCS-файлов на
аналогичные с .gz, но если изначально работать с ними, то ничего менять и не
придется. При изменении самих ресурсов нужно будет снова их заархивировать и
поменять строку вызова в HTML-файлах (чтобы избежать кеширования). При
промышленном подходе к разработке, все эти действия автоматизируются, а при
кустарном — трудозатраты не так существенны по сравнению с увеличением скорости
загрузки сайта (если, конечно, не собирать проект прямо на боевом сайте, без
конца gzip'я один и тот же файл :).
Старая версия правил (без учета Konqueror'а) тестировалась
здесь, полет нормальный.
Спасибо всем, кто дочитал до конца. Буду рад комментариям и добавлениям.
Автор перевода:
http://sunnybear.habrahabr.ru/
|