Перейти к содержанию
Innovialabs

Кэширование в браузере: Cache-Control, ETag и сброс кэша

Практика3 мин

Коротко

Статику с хэшем в имени файла кэшируйте надолго с immutable, а HTML отдавайте с no-cache и ETag — тогда пользователи получают обновления сразу, а повторные загрузки почти мгновенны.

Короткий ответ

Браузер решает, брать файл из кэша или идти на сервер, по заголовкам ответа. Рабочая схема для большинства сайтов:

  • Статика с хэшем в имени (app.3f9a2c.js, logo.81bd.svg) — Cache-Control: public, max-age=31536000, immutable. Файл с таким именем никогда не меняется, поэтому его можно хранить год.
  • HTML и API-ответы — Cache-Control: no-cache плюс ETag или Last-Modified. Браузер каждый раз спрашивает сервер «изменилось ли?», и если нет — получает короткий ответ 304 Not Modified без тела.
  • Личные данные — Cache-Control: private, no-store.

Главные заголовки

ЗаголовокЧто делает
max-age=NОтвет свежий N секунд, сервер не спрашивается
no-cacheХранить можно, но перед использованием нужна проверка на сервере
no-storeНе сохранять вообще
private / publicТолько браузер / также CDN и прокси
immutableФайл не изменится, не нужно перепроверять даже при обновлении страницы
s-maxage=NОтдельный срок для CDN и общих кэшей
ETag«Отпечаток» версии ресурса
Last-ModifiedДата последнего изменения

Частая путаница: no-cache не значит «не кэшировать». Это значит «кэшировать, но всегда перепроверять». Запрет хранения — это no-store.

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

  1. Сервер отдает файл с ETag: "abc123".
  2. Срок свежести истек (или стоит no-cache), браузер отправляет If-None-Match: "abc123".
  3. Если версия та же, сервер отвечает 304 без тела — экономится трафик, но не сам запрос.
  4. Если версия новая — приходит 200 с новым содержимым и новым ETag.

Ревалидация дешевле полной загрузки, но это все равно сетевой запрос. Поэтому для статики лучше вообще избегать запросов через долгий max-age.

Сброс кэша через хэш в имени

Если отдать styles.css с max-age на год, пользователи не увидят новую версию. Решение — cache busting: сборщик (Vite, webpack, Next.js) добавляет в имя файла хэш содержимого. Изменился код — изменился хэш — изменилось имя — браузер скачивает новый файл.

Важное условие: HTML, который ссылается на эти файлы, нельзя кэшировать надолго. Иначе старый HTML будет указывать на старые ассеты. Пример настройки nginx:

location /assets/ {
    add_header Cache-Control "public, max-age=31536000, immutable";
}

location / {
    add_header Cache-Control "no-cache";
    try_files $uri $uri/ /index.html;
}

Вариант с ?v=2 в адресе тоже работает, но его легко забыть обновить вручную, а хэш сборщик проставляет сам.

Как проверить кэш в DevTools

  • Откройте вкладку Network, выберите запрос и посмотрите Response Headers: какой Cache-Control, есть ли ETag.
  • Колонка Size покажет (memory cache) или (disk cache) — файл взят из кэша без сети. Статус 304 — была ревалидация.
  • Галочка Disable cache отключает кэш, только пока DevTools открыты. Для проверки реального поведения ее нужно снять.
  • Обычная перезагрузка может перепроверять ресурсы, поэтому тестируйте также переход по ссылке внутри сайта.
  • Учитывайте CDN: заголовки вроде Age или X-Cache (зависит от провайдера) показывают, ответил ли промежуточный кэш.

Частые ошибки

  • HTML с долгим max-age. Пользователи днями видят старую версию сайта.
  • Долгий кэш у файлов без хэша. Обновили logo.png — у части посетителей старый логотип.
  • Ответы с персональными данными без private. CDN может отдать их другому пользователю.
  • Разные ETag на разных серверах за балансировщиком — браузер постоянно скачивает файл заново.
  • Надежда на Expires. Если указан max-age, он важнее; достаточно использовать Cache-Control.

Частые вопросы

Оба работают для ревалидации. ETag точнее, потому что отражает содержимое, а не время. Можно отдавать оба: браузер пришлет соответствующие условные заголовки, а сервер проверит их.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.