Как получать всегда свежие данные на клиенте несмотря на кэширование
Что проверяют
Различаете ли вы уровни кэша: HTTP-кэш браузера, CDN, Service Worker, кэш клиентской библиотеки данных. И знаете ли, что «всегда свежие» не значит «совсем без кэша». Следом обычно спрашивают, чем no-cache отличается от no-store.
Как отвечать
Сначала договоритесь о цели: обычно нужна не отмена кэша, а дешёвая проверка актуальности. Дальше по слоям:
- HTTP-заголовки:
Cache-Control: no-cacheразрешает хранить ответ, но требует ревалидации перед каждым использованием, аno-storeзапрещает хранение совсем. В паре сETagсервер отвечает304 Not Modifiedбез тела, и свежесть почти ничего не стоит; - статика: хэш содержимого в имени файла плюс
max-age=31536000, immutable, а HTML отдаётся сno-cache. Новый билд меняет имена, и старый кэш просто перестаёт использоваться; - CDN:
s-maxageзадаёт время жизни на прокси отдельно от браузера,stale-while-revalidateотдаёт старое и тут же обновляет в фоне, для срочного обновления есть purge; - fetch: опция
cache: 'no-store'или'no-cache'точечно для запроса, без правки сервера; - клиентские библиотеки: в TanStack Query и SWR свежесть задаётся
staleTime, рефетчем при фокусе окна и инвалидацией ключей после мутаций; - push вместо опроса: если данные должны меняться у пользователя на глазах, нужны SSE или WebSocket, а не частый polling.
Где спотыкаются
Путают no-cache с запретом кэширования и ставят его на всё подряд, включая статику. В итоге каждый заход тянет мегабайты, хотя неизменяемым файлам можно было дать год жизни.
Лечат проблему случайным ?t=Date.now() в каждом запросе. Это ломает кэш и на CDN, и в браузере, а настоящую причину, неверные заголовки или забытую инвалидацию после мутации, оставляет на месте.
Забывают про Service Worker и bfcache. Стратегия cache-first в воркере отдаёт старый ответ, как бы ни были настроены заголовки, а страница, восстановленная кнопкой «Назад», показывает прежние данные, пока вы не обработаете событие pageshow с event.persisted.