PassFront
  1. PassFront
  2. База знаний
  3. HTTP и HTTPS

Как работает HTTP-кеширование: Cache-Control, ETag и Last-Modified?

HTTP и HTTPS

Cache-Control определяет, сколько ответ свеж и кто может его хранить, а ETag и Last-Modified позволяют дёшево перепроверить устаревшую копию и получить 304 без тела.

Cache-Control

  • max-age=3600 — час без запросов к серверу; s-maxage — то же для общих кешей вроде CDN.
  • no-cache — хранить можно, но перед использованием обязательно перепроверить; no-store — не хранить вовсе.
  • private — только браузер, public — можно и CDN.
  • immutable — не перепроверять даже при перезагрузке; stale-while-revalidate=60 — отдать старое и обновить в фоне.

Валидация

  1. Сервер отдаёт ETag: "a1b2" или Last-Modified.
  2. Копия протухла — браузер шлёт If-None-Match: "a1b2" или If-Modified-Since.
  3. Ничего не изменилось — 304 Not Modified без тела, копия снова свежая.

Last-Modified имеет секундную точность, ETag надёжнее. Vary: Accept-Encoding велит хранить отдельный вариант на каждое значение заголовка.

Типовая стратегия

Статике с хешем в имени — год и immutable, HTML — no-cache. На клиенте:

await fetch('/', { cache: 'no-cache' }); // перепроверить по ETag
// 'force-cache' — взять даже устаревшую копию, 'reload' — мимо кеша
let etag, data;
async function load(url) {
  const res = await fetch(url, { cache: 'no-store', headers: etag ? { 'If-None-Match': etag } : {} });
  if (res.status === 304) return data;
  etag = res.headers.get('ETag');
  return (data = await res.json());
}
const [e] = performance.getEntriesByName(`${location.origin}/app.3f9c.js`);
console.log(e.transferSize ? 'по сети' : 'из кеша');

Коротко для собеседования

Кешем управляют два механизма: свежесть через Cache-Control и дешёвая перепроверка через ETag с ответом 304. Рабочая схема — статике с хешем в имени год и immutable, HTML — no-cache, иначе после деплоя пользователи застрянут на старой версии.

Другие вопросы раздела