Почему файл кэшируется и браузер может показывать старую версию файла?
Что проверяют
Понимаете ли вы механику HTTP-кэширования настолько, чтобы отличить «у пользователя старый файл» от «на сервере старый файл». От этого зависит, заведёте вы полезный дефект или потратите день команды на невоспроизводимый баг после релиза.
Как отвечать
Копию ответа хранит браузер, а правила хранения задаёт сам ответ:
Cache-Control: max-ageзадаёт срок свежести. Пока он не вышел, запроса к серверу нет вообще, ответ берётся из памяти или с диска;- после истечения браузер шлёт условный запрос с
If-None-MatchилиIf-Modified-Since, и сервер отвечает 304 без тела, если ничего не изменилось; ETagиLast-Modifiedэто валидаторы, по которым такое сравнение и делается;no-cacheразрешает хранить, но требует перепроверки,no-storeзапрещает хранить вовсе,immutableговорит не перепроверять до конца срока;- между вами и сервером есть ещё кэш CDN и прокси, а
Varyопределяет, считаются ли ответы для разных заголовков разными.
Отсюда типовое решение: хэш в имени файла (app.a1b2c3.js) плюс длинный срок жизни для статики и no-cache для HTML. Тогда новая сборка приходит по новому адресу и старого файла взяться неоткуда.
Для проверки: в обычном режиме, без галки отключения кэша, посмотреть статус и заголовки, повторить в приватном окне и запросить файл напрямую. Если старая версия приходит всем и в обход браузера, виноват CDN или деплой.
Где спотыкаются
Путают no-cache и no-store. Первый заголовок хранение разрешает, и дефект «личные данные остались в кэше» с ним вполне реален, а второй запрещает. Перепутанная пара даёт и ложные баги, и пропущенные.
Тестируют с открытыми инструментами разработчика и включённым отключением кэша. В таком режиме поведение пользователя не воспроизводится никогда, и проблема уезжает в прод.
Считают жёсткое обновление решением. Пользователь его не нажимает, поэтому старый бандл после релиза это дефект сборки или заголовков, а не мелочь, которую можно обойти вручную у себя.