Почему браузер игнорирует директивы Expires и max-age?
Потому что приоритет всегда у Cache-Control: если в ответе есть no-store, no-cache, must-revalidate или private, браузер отбрасывает Expires и max-age и каждый раз идёт на сервер. Дополнительно кэш отключают жёсткая перезагрузка Ctrl+F5 (запрос уходит с Cache-Control: no-cache), заголовок Vary со значением «*» и включённый чекбокс Disable cache в панели Network инструментов разработчика.
Проверять нужно по цепочке: DevTools → Network → выбрать запрос → Headers → Response Headers (что реально пришло от сервера, а не из кэша) → вкладка Application → Service Workers (перехват запросов активным воркером) → chrome://net-internals/#httpCache или chrome://net-export для журнала сетевых событий. Учтите два нюанса: Expires с неверным форматом даты или датой в прошлом игнорируется всегда, а ответы на POST и ответы со статусом 302 без явных заголовков кэширования по умолчанию не сохраняются.
