Зачем вообще нужен кеш
Когда пользователь открывает страницу, браузер запрашивает десятки файлов: HTML, CSS, JavaScript, картинки, шрифты. Каждый запрос — это время. Если сервер находится в Москве, а пользователь во Владивостоке, задержка составляет 140–200 мс только на передачу одного пакета. Умножь на количество файлов — и получишь сайт, который грузится три-четыре секунды.
Кеш позволяет сохранить файл у пользователя или на промежуточном сервере, чтобы при следующем запросе не тянуть его заново. Браузер загрузил CSS-файл сегодня — завтра возьмёт его из локального кеша за миллисекунды.
Это влияет не только на скорость, но и на нагрузку сервера. Меньше запросов — меньше CPU и памяти тратится на обработку. Для сайтов с тысячами посетителей в день разница ощутимая.
Виды кеширования: что где живёт
Кеш бывает на разных уровнях, и каждый работает по-своему.
Браузерный кеш — файлы сохраняются прямо на компьютере или телефоне пользователя. Управляется HTTP-заголовками, которые отдаёт сервер.
Серверный кеш — сервер сохраняет готовые HTML-страницы или результаты запросов к базе данных, чтобы не генерировать их каждый раз заново. Типичные инструменты — Nginx FastCGI Cache, Varnish, Redis, Memcached.
CDN (Content Delivery Network) — сеть распределённых серверов по всему миру. Статические файлы (картинки, CSS, JS) хранятся на ближайшем к пользователю узле. Cloudflare, Fastly, AWS CloudFront — популярные варианты.
Кеш приложения — внутри кода. Например, результат тяжёлого SQL-запроса сохраняется в Redis на 5 минут, и следующая тысяча пользователей получает его мгновенно.
Хорошо настроенный сайт использует все четыре уровня. Но начинать стоит с браузерного — он самый простой и даёт ощутимый результат сразу.
HTTP-заголовки кеширования: основа основ
Браузер понимает кеш через заголовки, которые сервер отправляет вместе с файлом.
Cache-Control
Главный заголовок. Говорит браузеру, как долго хранить файл и при каких условиях:
Cache-Control: max-age=31536000, immutable
max-age=31536000 — хранить год (в секундах). Подходит для статики, которая не меняется: шрифты, библиотеки. immutable говорит браузеру, что файл точно не изменится даже при ручном обновлении страницы.
Cache-Control: no-cache
Не означает «не кешировать». Означает «каждый раз проверяй у сервера, не изменился ли файл». Если не изменился — берёт из кеша.
Cache-Control: no-store
Вот это уже «никогда не сохранять». Подходит для страниц с личными данными, банковских форм.
Cache-Control: public, max-age=86400
public разрешает кешировать промежуточным серверам (CDN, прокси). max-age=86400 — сутки.
Cache-Control: private, max-age=3600
private — только браузер, CDN не кешируют. Например, для страниц профиля пользователя.
ETag и Last-Modified
Эти заголовки работают в паре с no-cache. Сервер отдаёт файл с меткой:
ETag: "abc123"
Last-Modified: Wed, 01 Jan 2026 12:00:00 GMT
При следующем запросе браузер спрашивает: «Файл с этой меткой ещё актуален?» Если да — сервер возвращает 304 Not Modified без тела, и браузер достаёт файл из кеша. Экономия трафика и времени без лишней нагрузки на канал.
Как настроить кеш в Nginx
Если сайт работает на Nginx, базовые настройки кеширования добавляются в конфиг за несколько минут:
location ~* \.(css|js|woff2|woff|ttf)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location ~* \.(jpg|jpeg|png|gif|webp|svg|ico)$ {
expires 30d;
add_header Cache-Control "public";
}
location ~* \.(html|htm)$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
Шрифты и библиотеки — год, они не меняются. Картинки — месяц. HTML — час, потому что контент меняется чаще.
Важный момент: если CSS-файл закешировался на год, а ты его изменил — пользователь не увидит изменений до истечения срока. Решение — cache busting: добавлять хеш к имени файла при сборке. style.css превращается в style.abc123.css. Новый файл — новый URL — браузер скачает его заново. Большинство сборщиков (Webpack, Vite) делают это автоматически.
Серверный кеш страниц
Браузерный кеш помогает конкретному пользователю. Но если тысяча человек одновременно открывают главную страницу — сервер генерирует её тысячу раз. Серверный кеш решает это: сохраняет готовый HTML и отдаёт всем без лишней работы.
Nginx FastCGI Cache
Если сайт на PHP (WordPress, Laravel), можно включить FastCGI Cache:
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=SITE:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
server {
set $skip_cache 0;
if ($http_cookie ~* "wordpress_logged_in") {
set $skip_cache 1;
}
if ($request_uri ~* "/(cart|checkout|my-account)") {
set $skip_cache 1;
}
location ~ \.php$ {
fastcgi_cache SITE;
fastcgi_cache_valid 200 60m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
}
}
Авторизованным пользователям и страницам корзины кеш не нужен — у них динамический контент. Это базовая схема, её нужно дополнять под конкретный проект.
Redis для кеша данных
Redis — in-memory хранилище, которое работает как сверхбыстрая база данных. Типичный сценарий: результат запроса к базе (например, список товаров) сохраняется в Redis на несколько минут.
import redis
import json
r = redis.Redis(host='localhost', port=6379, db=0)
def get_products():
cache_key = 'products_list'
cached = r.get(cache_key)
if cached:
return json.loads(cached)
products = db.query("SELECT * FROM products WHERE active = 1")
r.setex(cache_key, 600, json.dumps(products)) # 600 секунд
return products
Паттерн называется Cache-Aside (Lazy Loading): сначала смотрим в кеш, при промахе идём в базу.
Главный вопрос при работе с Redis — инвалидация. Когда менеджер обновляет товар в админке, нужно сбросить соответствующий ключ:
r.delete('products_list')
Если забыть — пользователи видят устаревшие данные.
CDN: кеш на краю сети
CDN особенно важен, если аудитория разбросана географически. Cloudflare бесплатно кеширует статику и распределяет её по 200+ точкам присутствия по всему миру.
Базовая настройка через Cache Rules в Cloudflare:
- Статика (CSS, JS, изображения) — Edge Cache TTL: 1 месяц
- HTML-страницы блога — Edge Cache TTL: 4 часа
- Страницы с динамическим контентом — Bypass Cache
После включения CDN скорость загрузки для пользователей из дальних регионов может вырасти в 2–3 раза. Latency от Москвы до Владивостока составляет ~140 мс, от ближайшего узла Cloudflare — 15–20 мс. Разница прямая.
Кеш в WordPress
WordPress без кеша — это боль. Каждый запрос страницы генерирует 30–80 запросов к базе данных. При небольшом трафике терпимо, при нагрузке сервер ложится.
Популярные плагины кеширования:
- WP Rocket — платный, самый удобный, настраивается за 15 минут
- W3 Total Cache — бесплатный, много настроек, легко запутаться
- LiteSpeed Cache — если хостинг использует LiteSpeed
Что включить в любом из них:
- Page Cache — сохраняет готовый HTML
- Минификация CSS и JS — меньше файлов, меньше запросов
- Lazy loading изображений — грузить картинки по мере прокрутки
- Database Cache — через Redis или Memcached
Один нюанс: после установки плагина кеша обязательно проверь формы, корзину и авторизацию. Иногда кеш захватывает динамические элементы и ломает их поведение.
Что точно не надо кешировать
Кеш не везде помогает. Список того, что кешировать опасно:
- Страницы авторизованных пользователей (профиль, история заказов)
- Корзина и процесс оформления заказа
- Страницы с CSRF-токенами
- API-ответы с персональными данными
- Страницы с данными реального времени (котировки, чаты)
Если сомневаешься — лучше не кешировать, чем показать одному пользователю данные другого. Второй вариант — уже проблема безопасности.
Как убедиться, что кеш работает
Самый простой способ — заголовки ответа в DevTools. Открой вкладку Network, найди нужный файл и посмотри Response Headers:
Cache-Control: max-age=31536000 — кеш настроен
cf-cache-status: HIT — файл отдан из кеша Cloudflare
Status: 304 Not Modified — браузер использовал локальный кеш
Google PageSpeed Insights прямо указывает файлы без кеширования или с коротким TTL в разделе «Эффективно используйте кеш браузера».
Для проверки серверного кеша Nginx можно добавить отладочный заголовок:
add_header X-Cache-Status $upstream_cache_status;
Он покажет HIT, MISS, BYPASS или EXPIRED для каждого запроса.
Типичные ошибки при настройке кеша
Слишком длинный TTL для HTML. Закешировал главную страницу на неделю, обновил акцию — пользователи неделю видят старую. Для HTML разумный максимум — несколько часов.
Кешируется авторизованный контент. Пользователь A зашёл на свою страницу профиля, кеш её сохранил. Пользователь B открыл тот же URL — получил данные A. Серьёзная проблема безопасности.
Нет инвалидации. Обновил товар, но забыл сбросить кеш. Половина пользователей видит старую цену, половина — новую.
Cache busting не настроен. Обновил CSS, имя файла не изменилось. Пользователи с долгим кешем видят сломанную верстку.
Кешируются ошибки. Сервер вернул 500, CDN закешировал ошибку на час. Теперь тысячи пользователей видят ошибку даже после её исправления. Никогда не кешируй ответы с кодами 4xx и 5xx — большинство CDN делают это правильно по умолчанию, но стоит проверить явно.
Кеширование — одна из тех вещей, которые при правильной настройке работают незаметно, но без них сайт ощущается медленным и нагружает сервер впустую. В REEXY вопрос кеша решается на этапе разработки: конфиги Nginx, Redis и базовая настройка CDN входят в стандартный процесс. Но даже если сайт уже готов, большинство изменений из этой статьи можно внедрить самостоятельно за пару часов — главное, не забыть проверить результат через DevTools.