Кэширование: Cache-Control, ETag, Last-Modified
Кэширование: Cache-Control, ETag, Last-Modified
Каждый раз загружать сайт с нуля — долго и накладно. Логотип, CSS, шрифты и скрипты не меняются годами, но браузер по умолчанию запрашивает их снова и снова. HTTP-кэширование решает эту проблему: сохранённая копия используется повторно без запроса к серверу.
Зачем нужно кэширование
Кэширование экономит время и трафик. Когда браузер запрашивает style.css, который не менялся полгода, сервер может ответить «не изменился, бери из кэша» — и страница загрузится на сотни миллисекунд быстрее. Это работает на всех уровнях: браузер, CDN, прокси-серверы.
Cache-Control: главный заголовок кэширования
Cache-Control — директива, которая говорит, можно ли кэшировать ответ и на сколько:
Cache-Control: max-age=3600, public
Составляющие:
- max-age=N. Сколько секунд ответ свежий.
max-age=3600— час можно использовать из кэша без запроса к серверу. - public. Можно кэшировать всем: и браузеру, и промежуточным прокси (CDN).
- private. Только браузеру. Ответ содержит персональные данные — не для CDN.
- no-cache. Кэшировать можно, но перед использованием ОБЯЗАТЕЛЬНО переспросить сервер (условный запрос).
- no-store. Не кэшировать вообще. Для самых чувствительных данных (банковские операции).
Условные запросы: ETag и Last-Modified
Что если max-age истёк? Браузер делает условный запрос: «у меня есть версия X, она ещё актуальна?»
ETag — уникальный идентификатор версии ресурса. Сервер вычисляет хэш от содержимого и возвращает в заголовке:
HTTP-ответ: ETag: "abc123def456"
В следующий раз браузер спрашивает: «изменился ли ресурс с ETag abc123def456?»:
HTTP-запрос: If-None-Match: "abc123def456"
Если не изменился, сервер отвечает 304 Not Modified с пустым телом — экономя трафик. Если изменился — 200 OK с новым телом и новым ETag.
Last-Modified — дата последнего изменения. Проще ETag, но менее точно (дата может не измениться при одинаковом содержимом, или измениться при перезаписи тем же содержимым):
HTTP-ответ: Last-Modified: Tue, 29 Apr 2026 18:00:00 GMT
HTTP-запрос: If-Modified-Since: Tue, 29 Apr 2026 18:00:00 GMT
Стратегии кэширования
Разные ресурсы требуют разного подхода:
- Статические файлы с хэшем в имени.
main.abc123.js,style.def456.css. Имя меняется при изменении содержимого. Можно кэшировать бесконечно:Cache-Control: max-age=31536000, immutable. - HTML-страницы. Меняются часто, нужен условный запрос:
Cache-Control: no-cache+ ETag. - API-ответы. Часто вообще не кэшируются (
no-store) или кэшируются на секунды для сглаживания пиков (max-age=5, private). - Изображения и шрифты. Меняются редко, кэшируются агрессивно:
max-age=2592000(30 дней) или дольше.
Service Workers и Cache API
Современные веб-приложения используют Service Workers для тонкого контроля над кэшированием: можно кэшировать всё при первом посещении и работать офлайн (PWA). Это уже не HTTP-кэш, а программный — разработчик сам решает, что и когда кэшировать. Подробнее — в курсе по JavaScript.
Проверь себя
- Чем
no-cacheотличается отno-store? - Зачем нужен ETag, если есть Last-Modified?
- Что ответит сервер, если
If-None-Matchсовпадает с текущим ETag?
no-cacheразрешает кэшировать, но требует проверки (условный запрос) перед каждым использованием.no-storeвообще запрещает кэширование.- ETag точнее: он меняется только при изменении содержимого. Last-Modified может измениться при восстановлении файла с тем же содержимым, или не измениться при быстрой перезаписи.
304 Not Modifiedбез тела. Браузер использует копию из кэша.
Что унести с урока
Cache-Controlуправляет кэшированием:max-age,public/private,no-cache/no-store.- Условные запросы (ETag + If-None-Match, Last-Modified + If-Modified-Since) перепроверяют кэш.
304 Not Modifiedэкономит трафик: сервер не шлёт тело повторно.- Стратегия кэширования зависит от типа ресурса: статика кэшируется агрессивно, HTML проверяется, API редко кэшируется.
В следующем уроке — Content Negotiation: как сервер выбирает формат и язык ответа.