Немного о заголовках для кеширования в HTTP

В протоколе HTTP названия директив для заголовка Cache-Control даны крайне неудачно, что часто вызывает путаницу у разработчиков CMS. Итак, попробуем разобраться, что каждая из них делает:
  • no-cache — не запрещает кеширование вообще, как это можно было бы ожидать из названия, а только указывает, что при каждом обращении к ресурсу нужно сначала сделать запрос на сервер с условными заголовками If-Modified-Since или If-None-Match, для проверки, что результат не изменился.
  • no-store — запрещает сохранение ответа в кеше. Именно эта директива и есть запрет кеширования. Повторное обращение к данному ресурсу будет отправлено на сервер, причем без заголовков типа If-Modified-Since.
  • must-revalidate — по названию можно было бы предположить, что она делает перепроверку изменения содержимого на сервере. Но на самом деле нет: эта директива указывает, что делать с контентом, у которого истёк max-age и нет возможности перезапросить его с сервера (например, в автономном режиме). Если директива указана, вместо страницы будет выдано сообщение, что она более недоступна. Если же её нет, то страница будет показана, даже несмотря на то, что она является устаревшей (stale в терминах протокола HTTP).
  • max-age — срок в секундах, в течение которого страница считается актуальной (не перешедшей в состояние устаревшей — stale). Если не указан, считается равным нулю.

Сценарии использования

  • Cache-Control: no-cache, no-store
    полный запрет кеширования вообще. Любое обновление — повторный запрос страницы с сервера без условных заголовков, при переходе в автономный режим — ошибка, что страница недоступна.
  • Cache-Control: no-cache
    при обновлении страницы — запрос к серверу с условными заголовками, в автономном режиме — показ страницы из кеша. Именно этот вариант заголовка должны выдавать CMS для выдачи динамических страниц для гостей в большинстве случаев.
  • Cache-Control: private, no-cache
    аналогично предыдущему пункту, но запрещает кеширование страницы на proxy-серверах. Такой вариант должен использоваться при выдаче страницы залогиненному пользователю, чтобы другие пользователи, подключенные через этот же proxy, не могли увидеть его данные.
  • Cache-Control: private, no-cache, must-revalidate
    вариант для тех страниц, которые не должны быть доступными в автономном режиме или после истечения сессии. Например, «личных кабинетов» различных сервисов, где выводятся персональные данные пользователя или баланс его счетов.
  • Cache-Control: max-age=31536000
    выдача контента с разрешением кеширования на год. Хорошо подходит для CSS, JavaScript, шрифтов и прочей статики.

Ошибочные сценарии

  • Cache-Control: no-cache, max-age=600
    в течение 10 минут будет выдаваться страница из кеша без каких-либо запросов на сервер вообще, в результате чего пользователь не будет видеть обновления.
  • Cache-Control: must-revalidate, max-age=600
    аналогично предыдущему варианту, но при этом страница так же не будет доступна в автономном режиме.
При подготовке материала использовалась статья «Caching best practices & max-age gotchas».