Статьи Архив статей

Автор: Вася Coy aka coyl One
Опубликована: 3 ноября 2008

Оптимизация загрузки страниц на практике

Наткнулся на кучу интересных статей на 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.

Читать дальше

Все комментарии (habrahabr.ru)