В блоге 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
, чтобы кэшировать необходимые файлы исходя из их MIME-типа (который обычно корректно задается сервером). В этом случае директивы могут быть такими:
ExpiresActive On ExpiresByType text/css A315360000
Этот способ в большинстве случаев лучше, так как кэширующие заголовки будут установлены в зависимости от типа содержимого, а не от расширения. На этом всё?
При использовании описанных подходов может возникнуть множество менее распространенных проблем:
Web Optimizer не только имеет великолепную поддержку различных техник кэширования для различных окружений, но и предоставляет несколько путей для форсированного обновления кэша (если контент изменился на сервере). Эту тему мы поднимем в одном из следующих постов.