Кэширование настроено неправильно
Браузер не кеширует статику, каждый раз загружает заново. Cache-Control, Expires, ETag.
Симптом
- Статические файлы (CSS, JS, изображения) загружаются каждый раз при переходе по сайту, даже если они не изменились.
- В инструментах разработчика (Network) все запросы к статику имеют статус 200 и отсутствуют заголовки
Cache-Control,ExpiresилиETag. - Время отклика страницы растёт из‑за повторных загрузок больших файлов.
- В логах сервера видны многочисленные GET‑запросы к тем же ресурсам.
Причина
Браузер кэширует ресурс только если сервер явно указывает, что файл можно хранить локально. Если в ответе отсутствуют заголовки Cache-Control, Expires, ETag или они заданы с нулевыми значениями, браузер считает файл «не кэшируемым» и каждый раз запрашивает его заново. Причины могут быть:
- Неправильная конфигурация веб‑сервера – отсутствуют директивы, задающие кэш‑политику для статических файлов.
- Обратный прокси / CDN – перезаписывает заголовки, убирая кэш‑инструкции.
- Неправильный MIME‑тип – некоторые типы файлов не кэшируются по умолчанию.
- Сжатие – если включено gzip/deflate, но не выставлен
ETag, браузер не может использовать кэш.
Как проверить
-
Проверка заголовков в ответе
bash curl -I https://example.com/static/app.cssИщите строки:Cache-Control: Expires: ETag: -
Проверка в инструментах разработчика
- Откройте вкладку Network.
- Перезагрузите страницу.
- Выберите любой статический файл и посмотрите заголовки ответа. -
Проверка конфигурации сервера
- Для Nginx:nginx -T | grep -i cache
- Для Apache:apachectl -t -D DUMP_MODULESи проверьте наличиеmod_headers. -
Проверка прокси/CDN
- Отключите временно CDN (если используется) и повторите запросы.
- Смотрите заголовки, которые приходят от прокси (Via,X-Cache).
Решение
1. Настройка Nginx
# Для всех статических файлов
location ~* \.(css|js|png|jpg|jpeg|gif|svg|ico|woff2?)$ {
expires 30d; # срок жизни в кэше
add_header Cache-Control "public, max-age=2592000, immutable";
add_header ETag $upstream_cache_status;
try_files $uri =404;
}
expires 30d– устанавливает заголовокExpiresиCache-Controlс 30‑дневным сроком.immutableсообщает браузеру, что файл не меняется, можно хранить без проверки.add_header ETagдобавляет уникальный идентификатор, позволяющий использоватьIf-None-Match.
2. Настройка Apache
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 30 days"
ExpiresByType application/javascript "access plus 30 days"
ExpiresByType image/webp "access plus 30 days"
ExpiresByType image/svg+xml "access plus 30 days"
</IfModule>
<IfModule mod_headers.c>
Header set Cache-Control "public, max-age=2592000, immutable"
</IfModule>
3. Проверка после изменений
curl -I https://example.com/static/app.css
Ответ должен содержать:
Cache-Control: public, max-age=2592000, immutable
Expires: Mon, 25 Apr 2026 00:00:00 GMT
ETag: "abcd1234"
4. Очистка кэша браузера
После обновления заголовков браузер может продолжать использовать старые файлы. Очистите кэш вручную или дождитесь истечения срока жизни.
5. Если используется CDN
- В настройках CDN включите «Cache Static Resources» и задайте TTL (например, 30 дней).
- Убедитесь, что CDN не переопределяет заголовки сервера.
Связанные
Не хотите разбираться сами?
Запустите технический аудит сайта за 5 минут — получите PDF-отчёт с разбором всех 64 параметров и конкретными точками роста. Или закажите комплексное SEO-продвижение сайта — починим всё это и возьмём на себя дальнейшую оптимизацию.