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

Перевод: Глеб Кондратенко
Опубликована: 20 ноябоя 2009

Клиентское кэширование: основы, автоматизация, препятствия

В блоге Web Optimizer (продукта для автоматизации клиентской оптимизации) Николай Мациевский регулярно публикует интересные посты о клиентской оптимизации, раскрывая всё новые подробности этого перспективного направления в веб-разработке. По ряду причин Николай пишет статьи на английском языке. Чтобы все статьи были доступны и на русском языке, я предложил ему свою помощь с переводом. Далее перевод первой статьи из серии, посвященной тонкостям кэширования в клиентской оптимизации.

Определение правильного подхода для организации клиентского кэширования с учетом всех возможных нюансов отняло у меня достаточно много времени. Давайте рассмотрим весь путь по шагам.

Основы кэширования

Очень просто кэшировать один произвольный файл. Достаточно лишь добавить к запросу заголовок Cache-Control (для HTTP/1.1) и заголовок Expires (для HTTP/1.0). Заголовки будут выглядеть следующим образом:

Expires: Thu, 31 Dec 2019 23:55:55 GMT
Cache-Control: max-age=315360000

Все действительно настолько просто? Ну, практически.

Кэширование на прокси-серверах

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

Можно ли влиять на этот процесс? В RFC 2616 описан способ, позволяющий сообщить прокси-серверам, что содержимое желательно кэшировать: Cache-Control: public. Приведенный выше пример примет следующий вид:

Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000, public

Автоматизация кэширования

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

ExpiresActive On
ExpiresDefault "access plus 10 years"

Выглядит достаточно просто, какие могут быть проблемы?

Что именно следует кэшировать?

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

ExpiresActive On
ExpiresDefault "access plus 10 years"
<FilesMatch \.(html|xhtml|xml|shtml|phtml|php)$>
 ExpiresActive Off
</FilesMatch>

Но что если часть CSS- и JS-файлов, а может быть и часть изображений на сайте создаются динамически? Например, если картинки для предпросмотра и ряд стилей создаются при помощи PHP на лету?

ExpiresByType — наша волшебная палочка!

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

ExpiresActive On
ExpiresByType text/css A315360000

Этот способ в большинстве случаев лучше, так как кэширующие заголовки будут установлены в зависимости от типа содержимого, а не от расширения. На этом всё?

Возможные препятствия

При использовании описанных подходов может возникнуть множество менее распространенных проблем:

  • У ряда ресурсов (например, у файлов шрифтов) могут быть нестандартные MIME-типы. В подобных ситуациях заголовки кэширования могут быть применены только на основания расширения файлов с использованием FilesMatch. Но поскольку сложно гарантировать одинаковое поведение произвольного серверного окружения, лучше сочетать оба подхода: устанавливать заголовки с помощью FilesMatch и ExpiresByType.
  • Как определять какие файлы кэшировать? Web Optimizer имеет огромное количество предопределенных MIME-типов и расширений, позволяющих обработать практически любые статические ресурсы на сервере. В нем также есть несколько вариантов управления режимами кэширования.
  • Если на сервере отсутствует поддержка mod_expires, ее можно эмулировать при помощи light PHP proxy. В случае, если отсутствует mod_rewrite, можно организовать внутренние редиректы для всех ресурсов на этот прокси и все файлы будут закэшированы.
  • Если же на сервере нет поддержки ни mod_expires ни mod_rewrite, необходимо разбирать HTML-код и заменять все вызовы статических ресурсов их эквивалентами используя PHP proxy. Только и всего.

Web Optimizer не только имеет великолепную поддержку различных техник кэширования для различных окружений, но и предоставляет несколько путей для форсированного обновления кэша (если контент изменился на сервере). Эту тему мы поднимем в одном из следующих постов.

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

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