Кеширование сайта: браузер, CDN и сервер без устаревших данных
Кеширование сайта сокращает число повторных вычислений и загрузок: браузер использует уже полученные файлы, CDN отвечает с ближайшего узла, а сервер возвращает заранее подготовленный результат. Главная инженерная задача — не просто включить кеш, а определить, что именно можно сохранять, на какой срок и каким событием должна запускаться актуализация.
Почему кеш становится источником ошибок
Без явной стратегии разные уровни начинают хранить разные версии одного ресурса. Разработчик обновляет CSS, сервер уже отдает новый файл, но браузер продолжает использовать старый. Или CDN сохраняет HTML со сведениями, которые должны меняться для каждого пользователя. В результате интерфейс выглядит сломанным, опубликованные изменения не видны, а персональные данные рискуют попасть в общий кеш.
Кеширование не следует смешивать с соседними задачами производительности. Gzip и Brotli уменьшают объем передаваемых данных, но не определяют срок их хранения. TTFB характеризует задержку до первого байта, однако сам по себе не объясняет политику кеша. Оптимизация изображений относится к формату, размеру и загрузке медиаресурсов. Здесь рассматриваются только хранение копий и правила их обновления.
Три уровня кеша и их ответственность
Браузер
Браузерный кеш управляется заголовками ответа. Директива Cache-Control: max-age=3600 разрешает считать ответ свежим в течение часа. public допускает хранение в общих кешах, а private ограничивает его браузером конкретного пользователя. no-store запрещает сохранять ответ; no-cache не запрещает хранение, но требует проверить актуальность перед повторным использованием.
Для проверки применяются валидаторы. Сервер может передать ETag, после чего браузер отправит If-None-Match. При совпадении сервер ответит 304 Not Modified без тела документа. Аналогично работают Last-Modified и If-Modified-Since, хотя отметка времени обычно менее точна, чем идентификатор версии.
CDN и промежуточные кеши
CDN полезен для публичных ресурсов, одинаковых для всех посетителей. Директива s-maxage задает срок свежести именно для общего кеша и может отличаться от браузерного max-age. Например, Cache-Control: public, max-age=60, s-maxage=600 позволяет браузеру хранить ответ минуту, а CDN — десять минут.
Если ответ зависит от заголовка запроса, сервер должен корректно сформировать Vary. Например, Vary: Accept-Encoding разделяет варианты представления. Добавлять в Vary заголовки с большим количеством возможных значений без необходимости опасно: коэффициент попаданий снижается, а число копий растет.
Сервер и приложение
На сервере могут кешироваться HTML, результаты шаблонизации, запросы к базе данных и ответы внутренних API. Такой кеш не виден браузеру напрямую, поэтому для него нужны собственные ключи, сроки жизни и механизм сброса. Ключ должен включать все параметры, влияющие на результат: URL, язык, регион, тип устройства или права доступа — но только если приложение действительно формирует разные ответы.
Практическая матрица правил
| Ресурс | Рекомендуемый подход | Обновление |
|---|---|---|
| CSS и JavaScript с хешем в имени | public, max-age=31536000, immutable |
Новое имя файла при каждой сборке |
| Шрифты и неизменяемая статика | Длительный публичный кеш | Версионирование URL при замене |
| Публичная HTML-страница | Короткий срок или обязательная ревалидация | Сброс CDN после публикации |
| Каталог или лента | Короткий серверный/CDN-кеш при одинаковом ответе | Сброс по изменению сущности |
| Личный кабинет, корзина | private, no-store для чувствительных ответов |
Не помещать в общий кеш |
| API с публичными данными | Срок зависит от допустимой задержки обновления | TTL и событийная инвалидация |
Годовой срок безопасен только для ресурсов с уникальным версионным URL. Если содержимое файла /app.css меняется без изменения адреса, длительный max-age оставит часть пользователей на старой версии. Надежный вариант — имя вроде /app.a81f3c.css: новая сборка создает новый URL, а старый файл можно спокойно хранить до истечения срока.
Диагностический алгоритм
- Выберите конкретный URL. Проверяйте отдельно HTML, CSS, JavaScript и API-ответ. У разных типов ресурсов должны быть разные правила.
- Зафиксируйте первый ответ. В инструментах разработчика откройте Network и запишите статус,
Cache-Control,Age,ETag,Last-Modified,Varyи служебный заголовок CDN, если он присутствует. - Повторите запрос. Не включайте принудительное отключение кеша. Определите источник ответа: память браузера, диск,
304, CDN или исходный сервер. - Измените ресурс штатным способом. Опубликуйте тестовую правку и проверьте, поменялся ли URL версионной статики либо был ли сброшен кеш динамического документа.
- Проверьте анонимный сеанс. Откройте URL без авторизационных cookie. Это помогает отделить приватный вариант от публичного.
- Сравните несколько точек. Запрос с параметром обхода кеша допустим как диагностический прием, но не как постоянное решение. Сравните тело, заголовки и версию ресурса.
Для командной проверки полезно сохранять полный набор заголовков через curl -I https://example.ru/resource. Повторный запрос с If-None-Match позволяет отдельно проверить ревалидацию. Перед выводами учитывайте, что запрос HEAD может обрабатываться иначе, поэтому спорный результат следует подтвердить обычным GET.
Проверяемые критерии корректной настройки
- У каждого класса ресурсов определена явная политика, а не случайные значения веб-сервера.
- Версионная статика получает новый URL при изменении содержимого.
- Персональные и чувствительные ответы не сохраняются общим кешем.
- После публикации новая HTML-версия появляется в пределах заявленного TTL или после инвалидации.
- Условный запрос к неизмененному ресурсу возвращает
304, если используется ревалидация. - Ключ серверного кеша учитывает параметры, которые действительно изменяют ответ.
- Правила CDN и исходного сервера не противоречат друг другу.
- Механизм сброса проверен на тестовом изменении, а не только описан в конфигурации.
Типовые ошибки
Одинаковый TTL для всех ответов
Статический файл со стабильным адресом и страница корзины имеют разный риск устаревания. Универсальное правило либо лишает статику пользы длительного хранения, либо делает динамические данные небезопасными.
Сброс всего кеша при каждом изменении
Полная очистка проста, но создает резкий поток запросов к исходному серверу. Точечная инвалидация по URL или тегам кеша обычно предсказуемее. При этом связи нужно проектировать заранее: изменение товара может затрагивать его страницу, категорию и фрагменты витрины.
Версия только в query string
Параметр ?v=2 часто работает, но отдельное имя файла надежнее отражает неизменяемость ресурса и проще контролируется в цепочке прокси. Важно не само число, а гарантированное изменение URL вместе с содержимым.
Кеширование авторизованного HTML на CDN
Если CDN не различает пользователей, общий кеш может вернуть чужой вариант страницы. Такие ответы следует исключать из общего хранения, а наличие cookie не считать достаточной защитой без проверенного правила обхода кеша.
Границы метода
Корректный кеш уменьшает повторную работу, но не исправляет медленный код исходного запроса, чрезмерный размер файлов или ошибки клиентской логики. Низкий процент попаданий также не всегда означает неисправность: для уникальных персональных запросов он ожидаем. Метрики нужно оценивать по типам контента, а не одной средней величиной.
Публичная проверка показывает только то, что доступно по внешнему URL. Она не раскрывает внутреннее устройство серверного кеша, ключи хранилища или правила очистки в CMS. Эти части подтверждаются журналами приложения, конфигурацией инфраструктуры и контролируемыми тестовыми изменениями.
Итог
Устойчивая схема строится от характера данных. Неизменяемая статика получает долгий срок и версионный URL. Публичный динамический контент — ограниченный TTL, валидаторы и управляемую инвалидацию. Персональные ответы остаются приватными или не сохраняются вовсе. После настройки каждый сценарий необходимо проверить повторным запросом и публикацией новой версии.
Дополнительные материалы по технической диагностике собраны в блоге SiteVisor. Чтобы посмотреть публично доступные технические, SEO/GEO и конверсионные сигналы страницы без доступа к CMS, можно запустить бесплатную проверку SiteVisor. Результат внешней проверки следует сопоставлять с конфигурацией сервера и CDN.