Наткнулся на кучу интересных статей на webo.in и зачитался. Решил применить описанное там на реальном проекте. Вот что получилось. Проектик маленький — сайт моих друзей Bookcare. Они делают обложки для книг, а их сайт — мой «проект выходного дня».
Основная часть контента — это изображения обложек, которые хранятся в формате jpeg
. Значит действия над этой частью оптимизации сводятся к оптимизации самих картинок и настройке кеширования.
Для оптимизации картинок я использовал jpegtran
, однако проблема с ним была в том, что он не может обработать сразу всю папку — только по одному файлу. Другая проблема, что использовать входной файл в качестве выходного (просто перезаписать оптимизированный файл в старый) невозможно.
Я решил эту проблему небольшим скриптиком и, хотя я не очень силен в shell-скриптах, он работает и достаточно удобно производить замены. Итак, я создал в домашней папке скрипт jp.sh
:
jpegtran -copy none -optimize -perfect "$1" > "оsh_conv_$1" mv "$1" raw/ mv "оsh_conv_$1" "$1"
А затем выполнял простую последовательность:
mkdir raw find *.jpg -depth 0 -type f -iregex ".*\.jpg" -exec ~/s.sh {}
После этого в папке с картинками уже лежат оптимизированные джепеги, и создается новая папка raw/, содержащая исходные файлы. Папочка raw/
очень пригодилась, когда оказалось, что скриптик мой не отрабатывал на файлах с именами, содержащими не латиницу (файлы просто обнулялись). Сейчас все работает.
Итак, после того, как картинки удобным образом оптимизированы, надо было настроить кеширование. Я добавил выдачу ETag
. Это просто и описано на webo.in. Делается добавлением одной строки в .htaccess
FileETag MTime Size
Вообще-то надо еще настроить выдачу заголовков Expires, но это тоже делается несложно.
После разборок с картинками, они стали весить на 34% меньше, что на странице Каталога ускорило загрузку почти настолько же, так как основной контент — это именно картинки.
Далее я прошелся по хтмльной выдаче. Верстка не моя, по этому, я пока не полез в оптимизацию разметки, но базовые фичи сделал: убрал переносы строк, табы и повторяющиеся пробелы.
Далее интересней. Захотелось, чтобы все (даже пхпшные) странички выдавали Last-Modified
и правильно откликались на If-Modified-Since
.
Взглянул на главную страницу и понял, что там выводятся только новости и последние поступления (из динамического контента). Соответственно получил дату последней новости, дату последнего поступления, получил максимальную и обработал следующим образом:
// $md - Штамп даты последнего изменения $modified = gmdate("D, d M Y H:i:s",$md)." GMT";// Приводим к HTTPшному формату - "Mon, 20 Dec 2004 09:34:19 GMT"; $hdr = ''; $headers = apache_request_headers(); foreach ($headers as $header => $value) { if (eregi('If-Modified-Since', $header)) {$hdr = $value;} } if ($hdr === $modified) { header ("HTTP/1.1 304 Not Modified "); header ("Last-Modified: ". $modified); header ("Expires:"); header ("Cache-Control:"); exit(); } header ("Last-Modified: $modified"); header ("Expires:"); // обнуляем ненужные заголовки header ("Cache-Control:");
Надо отметить, что время в Last-Modified надо указывать всегда в GMT, то есть по Гринвичу.
Теперь страничка загружается один раз, а далее мы видим ответ 304 Not Modified
.
Еще одно важное замечание — заголовок Last-Modified
надо выдавать всегда, иначе страница будет загружаться через раз, так как в ответе 304 не было указано Last-Modified
. Такое поведение было замечено за FF3.
Затем добрался до выдачи css
в виде архивов. Тут меня не устроило решение, которое было дано на webo.in, так как на серваке bookcare.ru нет mod_headers
. Я использовал достаточно спорный метод, но в рамках данной задачи, я считаю, вполне законный:
RewriteEngine On AddEncoding gzip .css RewriteCond %{HTTP:Accept-encoding} !gzip [OR] RewriteCond %{HTTP_USER_AGENT} Konqueror RewriteRule ^(.*)\.css$ $1_css.nozip [L]
Соответственно, например main.css
у нас изначально лежит в виде архива, а main_css.nozip
— это обычная версия файла.
Если эти строки лежат в .htaccess
в отдельной папке, то никак не влияют на файлы вне этой папки, так что в таком виде этот прием только полезен. При минимальных действиях на сервере получается то, что должно получаться.
Вот, наверное, все, если я чего-нибудь не запамятовал.
UPD1: Все-таки запамятовал. После вырезания всех лишних символов из HTML-выдачи отдается она в gzip'ованом виде с коэффициентом сжатия 9.