После запуска сайта многие обнаруживают, что каждый второй запрос к серверу — полный. На мобильных устройствах LCP превышает 4 секунды. Типичный сайт с 1000 посетителей в день генерирует около 10 000 запросов, из которых 60% можно кэшировать. Причина — отсутствие или неверная настройка HTTP-кэширования. Наши инженеры настраивают Cache-Control и ETag, чтобы статика отдавалась из браузера мгновенно, а динамика проверялась без повторной передачи тела. Правильное кэширование сокращает число запросов на 80% и уменьшает LCP на 500–700 мс, напрямую влияя на Core Web Vitals. На одном из проектов настройка immutable и stale-while-revalidate снизила нагрузку на сервер на 60% и улучшила INP на 150 мс.
Как Cache-Control влияет на Core Web Vitals?
Core Web Vitals (LCP, CLS, INP) зависят от числа запросов и времени ответа сервера. Ресурсы с max-age=31536000 не запрашиваются с сервера год, что критически для мобильных пользователей с медленным интернетом. Сравнение: директива immutable исключает условные запросы при обновлении страницы, тогда как без неё браузер делает проверки If-Modified-Since или If-None-Match. Благодаря immutable эти проверки сокращаются на 100%, экономя до 200 мс на каждом ресурсе при перезагрузке. Использование ETag вместо Last-Modified даёт выигрыш в трафике до 5 раз для динамических ответов.
Какие директивы Cache-Control использовать?
| Директива | Значение |
|---|---|
| public | Кэшировать в браузере и на прокси/CDN |
| private | Только в браузере (не на CDN) |
| no-cache | Всегда проверять актуальность через сервер |
| no-store | Никогда не кэшировать |
| max-age=N | Кэшировать N секунд |
| s-maxage=N | Для CDN (переопределяет max-age) |
| immutable | Файл не изменится — не проверять даже при F5 |
| must-revalidate | После max-age — обязательно проверить |
Частые ошибки — забывают immutable для статики, не ставят Vary: Accept-Encoding, или для API используют public. Без Vary около 2-3% пользователей могут получить нечитаемый контент, если CDN отдаст gzip-версию без поддержки gzip.
Сравнение стратегий кэширования для разных типов контента
| Тип контента | Пример директив | Причина |
|---|---|---|
| JS/CSS (с хешем) | public, max-age=31536000, immutable |
Файл не меняется — можно кэшировать навсегда |
| HTML | public, max-age=300, must-revalidate |
Часто обновляется, но свежесть не критична |
| API | no-cache, no-store |
Данные меняются динамически |
| Изображения | public, max-age=2592000 |
Долгий кэш без immutable — могут быть перезалиты |
Когда использовать ETag вместо Last-Modified?
ETag — уникальный идентификатор версии ресурса, генерируемый на основе хеша содержимого. Last-Modified использует только дату, что менее точно. Если файл изменился, но дата осталась (баг сервера), Last-Modified не сработает. ETag обязателен для динамических страниц: сервер проверяет заголовок If-None-Match и возвращает 304 Not Modified, экономя до 100% размера ответа. В nginx ETag включён по умолчанию (etag on;). На одном проекте мы заменили Last-Modified на ETag и снизили трафик API на 40%.
Как настроить заголовки для статики и API?
Пример конфигурации Nginx
# Nginx конфигурация для всех типов ресурсов # Статические ассеты с хешем (Vite, Webpack) location ~* \.(js|css)$ { expires 1y; add_header Cache-Control "public, max-age=31536000, immutable"; add_header Vary Accept-Encoding; } # Шрифты — тоже immutable location ~* \.(woff2|woff|ttf|eot)$ { expires 1y; add_header Cache-Control "public, max-age=31536000, immutable"; add_header Access-Control-Allow-Origin *; } # Изображения — долгий кэш без immutable location ~* \.(webp|avif|jpg|jpeg|png|gif|svg|ico)$ { expires 30d; add_header Cache-Control "public, max-age=2592000"; } # HTML — короткий кэш с must-revalidate location ~* \.html$ { expires 5m; add_header Cache-Control "public, max-age=300, must-revalidate"; } # API — не кэшировать location /api/ { add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma no-cache; } Продвинутые техники: Stale-While-Revalidate и Vary
Директива stale-while-revalidate позволяет отдавать устаревший кэш мгновенно, а в фоне обновлять его. Пример: Cache-Control: public, max-age=300, stale-while-revalidate=3600 — пользователь получает данные за 0 мс, свежая версия подгружается асинхронно к следующему визиту. Это улучшает восприятие скорости — никаких задержек. Без stale-while-revalidate пришлось бы либо ставить короткий max-age (частые запросы) либо долгий (риск устаревших данных). По сравнению с простым max-age без ревалидации, эта директива сокращает время ожидания для пользователя на 100% при наличии устаревшего кэша.
Заголовок Vary гарантирует, что CDN учтёт кодировку сжатия. Без него около 2-3% пользователей могут получить нечитаемый контент, если CDN отдаст gzip-версию браузеру без поддержки gzip. Как указано в документации, это решает проблему полностью.
Процесс настройки под ключ
- Аудит — анализируем текущие заголовки, выявляем проблемные ресурсы (с помощью Chrome DevTools, Lighthouse).
- Проектирование — определяем стратегию для статики, HTML, API, изображений, шрифтов.
- Настройка Nginx/Apache — применяем директивы с учётом CDN.
- Внедрение ETag — для API и динамики генерируем хеши на основе даты изменения данных.
- Конфигурация CDN — устанавливаем
s-maxage,Vary, правила инвалидации. - Тестирование — проверяем через curl и инструменты (GTmetrix, WebPageTest).
- Документация — фиксируем схему кэширования и инструкцию по инвалидации.
Что вы получите
- Сокращение количества запросов на 80%.
- Улучшение LCP на 500–700 мс.
- Снижение нагрузки на сервер до 60%.
- Экономию на CDN-трафике до 70%.
- Подробный отчёт с аудитом и рекомендациями.
- Конфигурации Nginx/Apache для вашего стека.
- Документацию по инвалидации кэша для разработчиков.
- Консультацию по дальнейшей оптимизации.
Свяжитесь для консультации — мы покажем, каких улучшений можно добиться на вашем сайте. Опыт команды — 7 лет, более 50 проектов с настроенным кэшированием. Закажите аудит кэширования сегодня и получите детальный отчёт с рекомендациями.







