HTTP кэширование
Кроме серверного кэширования, которое мы описали в предыдущих разделах, веб-приложения также могут использовать кэширование на стороне клиента, чтобы сэкономить время для формирования и передачи одного и того же содержания страницы.
Чтобы использовать кэширование на стороне клиента, вы можете настроить [[yii\filters\HttpCache]] в качестве фильтра для действия контроллера, отображающего результат, который может быть закэширован на стороне клиента. [[yii\filters\HttpCache|HttpCache]] работает только для GET
и HEAD
запросов. Для этих запросов он может обрабатывать три вида HTTP заголовков, относящихся к кэшированию:
- [[yii\filters\HttpCache::lastModified|Last-Modified]]
- [[yii\filters\HttpCache::etagSeed|Etag]]
- [[yii\filters\HttpCache::cacheControlHeader|Cache-Control]]
- Заголовок
Last-Modified
- Заголовок
ETag
- Заголовок
Cache-Control
- Ограничитель кэша сессий
- SEO подтекст
Заголовок Last-Modified
Заголовок Last-Modified
использует временную метку timestamp, чтобы показать была ли страница изменена после того, как клиент закэшировал её.
Вы можете настроить свойство [[yii\filters\HttpCache::lastModified]], чтобы включить отправку заголовка Last-Modified
. Свойство должно содержать PHP-функцию, возвращающую временную метку UNIX timestamp времени последнего изменения страницы. Сигнатура PHP-функции должна совпадать со следующей,
/**
* @param Action $action объект действия, которое в настоящее время обрабатывается
* @param array $params значение свойства "params"
* @return int временная метка UNIX timestamp, возвращающая время последнего изменения страницы
*/
function ($action, $params)
Ниже приведён пример использования заголовка Last-Modified
:
public function behaviors()
{
return [
[
'class' => 'yii\filters\HttpCache',
'only' => ['index'],
'lastModified' => function ($action, $params) {
$q = new \yii\db\Query();
return $q->from('post')->max('updated_at');
},
],
];
}
Приведенный выше код устанавливает, что HTTP кэширование должно быть включено только для действия index
. Он генерирует Last-Modified
HTTP заголовок на основе времени последнего сообщения. Когда браузер в первый раз посещает страницу index
, то страница будет сгенерирована на сервере и отправлена в браузер; если браузер снова зайдёт на эту страницу и с тех пор ни один пост не обновится, то сервер не будет пересоздавать страницу и браузер будет использовать закэшированную на стороне клиента версию. В результате, будет пропущено как создание страницы на стороне сервера, так и передача содержания страницы клиенту.
Заголовок ETag
Заголовок "Entity Tag" (или коротко ETag
) используется для передачи хэша содержания страницы. Если страница была изменена, то хэш страницы тоже изменится. Сравнивая хэш на стороне клиента с хэшем, генерируемым на стороне сервера, кэш может определить, была ли станица изменена и требуется ли её передавать заново.
Вы можете настроить свойство [[yii\filters\HttpCache::etagSeed]], чтобы включить передачу заголовка ETag
. Свойство должно содержать PHP-функцию, возвращающий seed для генерации ETag хэша. Сигнатура PHP-функции должна совпадать со следующей,
/**
* @param Action $action объект действия, которое в настоящее время обрабатывается
* @param array $params значение свойства "params"
* @return string строка используемая как seed для генерации ETag хэша
*/
function ($action, $params)
Ниже приведён пример использования заголовка ETag
:
public function behaviors()
{
return [
[
'class' => 'yii\filters\HttpCache',
'only' => ['view'],
'etagSeed' => function ($action, $params) {
$post = $this->findModel(\Yii::$app->request->get('id'));
return serialize([$post->title, $post->content]);
},
],
];
}
Приведенный выше код устанавливает, что HTTP кэширование должно быть включено только для действия view
. Он генерирует ETag
HTTP заголовок на основе заголовка и содержания последнего сообщения. Когда браузер в первый раз посещает страницу view
, то страница будет сгенерирована на сервере и отправлена в браузер; если браузер снова зайдёт на эту страницу и с тех пор ни один пост не обновится, то сервер не будет пересоздавать страницу и браузер будет использовать закэшированную на стороне клиента версию. В результате, будет пропущено как создание страницы на стороне сервера, так и передача содержание страницы клиенту.
ETags позволяет применять более сложные и/или более точные стратегии кэширования, чем заголовок Last-Modified
. Например, ETag станет невалидным (некорректным), если на сайте была включена другая тема
Ресурсоёмкая генерация ETag может противоречить цели использования HttpCache
и внести излишнюю нагрузку, т.к. он должен пересоздаваться при каждом запросе. Попробуйте найти простое выражение, которое инвалидирует кэш, если содержание страницы было изменено.
Note: В соответствии с RFC 7232,
HttpCache
будет отправлять какETag
заголовок, так иLast-Modified
заголовок, если они оба были настроены. И если клиент отправляет какIf-None-Match
заголовок, так иIf-Modified-Since
заголовок, то только первый из них будет принят.
Заголовок Cache-Control
Заголовок Cache-Control
определяет общую политику кэширования страниц. Вы можете включить его отправку, настроив свойство [[yii\filters\HttpCache::cacheControlHeader]]. По-умолчанию будет отправлен следующий заголовок:
Cache-Control: public, max-age=3600
Ограничитель кэша сессий
Когда на странице используются сессии, PHP автоматически отправляет некоторые связанные с кэшем HTTP заголовки, определённые в настройке session.cache_limiter
в php.ini. Эти заголовки могут вмешиваться или отключать кэширование, которое вы ожидаете от HttpCache
. Чтобы предотвратить эту проблему, по умолчанию HttpCache
будет автоматически отключать отправку этих заголовков. Если вы хотите изменить это поведение, вы должны настроить свойство [[yii\filters\HttpCache::sessionCacheLimiter]]. Это свойство может принимать строковое значение, включая public
, private
, private_no_expire
и nocache
. Пожалуйста, обратитесь к руководству PHP о session_cache_limiter() для объяснения этих значений.
SEO подтекст
Поисковые боты, как правило, с уважением относятся к заголовкам кэширования. Поскольку некоторые из поисковых систем имеют ограничение на количество страниц для одного домена, которые они обрабатывают в течение определенного промежутка времени, то предоставление заголовков кэширования может помочь индексации, поскольку будет уменьшено число обрабатываемых страниц.
Заберите ссылку на статью к себе, чтобы потом легко её найти!
Раз уж досюда дочитали, то может может есть желание рассказать об этом месте своим друзьям, знакомым и просто мимо проходящим?
Не надо себя сдерживать! ;)