Підступна війна росії проти України. Орієнтовні втрати ворога
(станом на 07.08.2026)
1455420
осіб
439
літаків
354
гелікоптерів
12247
танків
25098
ББМ
47522
артилерія
1550
ППО
2008
РСЗВ
131068
машин
34
кораблі і катери

HTTP-заголовки кэширования (Cache-Control) 🚀 — подробный обзор

23/11/2025 Оновлено: 24/11/2025

Представьте, что вы каждое утро приходите в одно и то же кафе и спрашиваете бариста: “Какой кофе вы варите?”. Он перечисляет все меню. На следующее утро вы снова спрашиваете то же, и он снова перечисляет. Это пустая трата времени, правда? Логичнее было бы запомнить тот небольшой перечень доступного кофе и спрашивать его только тогда, когда он изменится.

Именно так работает кэширование в браузере. Без него ваш браузер при каждом посещении страницы вынужден заново загружать каждую картинку, скрипт и стиль. Это медленно и дорого. HTTP-заголовки кэширования — это инструкции, которые сервер дает браузеру: “Запомни этот файл на неделю” или “Проверяй этот файл при каждом визите”.

В этой статье я расскажу о том, как правильно настроить эти инструкции, чтобы ваш сайт летал, а сервер не “задыхался” от лишних запросов.

 

Главный игрок: Cache-Control

Раньше для кэширования использовали заголовок Expires, но сегодня стандартом де-факто является Cache-Control. Это мощный инструмент, который позволяет очень гибко управлять поведением кэша.

Он состоит из директив. Давайте разберем самые важные из них:

Директива Что она означает
max-age=3600 Файл считается “свежим” в течение указанного количества секунд (здесь — 1 час). Браузер даже не будет спрашивать сервер об этом файле, пока время не истечет.
public Файл может кэшироваться кем угодно: браузером, CDN, прокси-сервером. Идеально для статики.
private Файл предназначен для одного пользователя (например, страница профиля). Кэшировать может только браузер, но не CDN.
no-cache Внимание, ловушка! Это не значит “не кэшировать”. Это значит “кэшируй, но перед каждым использованием спрашивай сервер, не изменился ли файл” (валидация).
no-store Вот это действительно “не кэшировать нигде и никогда”. Используется для банковских данных и конфиденциальной информации.
must-revalidate Когда срок max-age истечет, браузер обязан проверить актуальность файла на сервере, а не использовать старую копию.

 

Как браузер узнает, что файл изменился? (Валидаторы)

Когда вы используете no-cache или когда истекает время max-age, браузер делает запрос к серверу: “У меня есть картинка, вот ее метка. Она все еще актуальна?”. Для этого существуют два заголовка-валидатора:

  • ETag (Entity Tag): Уникальный хеш-код файла (например, "33a64df551425fcc55e4d42a148795d9f25f89d4"). Если хеш на сервере совпадает с тем, что есть у браузера, сервер отвечает 304 Not Modified (тело файла не передается).
  • Last-Modified: Дата последнего изменения файла. Менее точный, чем ETag, но тоже популярный.

 

Практика: как настроить кэширование

Настройка зависит от того, какой веб-сервер вы используете. Если вы не уверены, советую прочитать мою статью о разнице между Nginx и Apache.

 

Вариант 1: Nginx (Самый эффективный)

Добавьте этот код в блок server вашего конфигурационного файла:

# Кэширование статики (картинки, шрифты) на 1 год
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
    expires 365d;
    add_header Cache-Control "public, no-transform";
}
# Кэширование HTML (не кэшируем или кэшируем с проверкой)
location ~* \.(html)$ {
    add_header Cache-Control "no-cache";
}

 

Вариант 2: Apache (.htaccess)

Если вы используете Apache, добавьте этот код в файл .htaccess в корне сайта. Вам понадобится модуль mod_expires.

<IfModule mod_expires.c>
    ExpiresActive On    
    # картинки
    ExpiresByType image/jpg "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"    
    # CSS и JS
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"    
    # По умолчанию
    ExpiresDefault "access plus 2 days"
</IfModule>
# Дополнительный контроль заголовков
<IfModule mod_headers.c>
    <FilesMatch "\.(js|css|xml|gz|html)$">
        Header append Vary: Accept-Encoding
    </FilesMatch>
</IfModule>

 

Вариант 3: PHP (для динамического контента)

Иногда нужно запретить кэширование конкретной динамической страницы (например, корзины). Это можно сделать прямо в коде:

<?php
// Запрещаем кэширование
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
?>

 

Вам интересно, как принудительно обновить кэш у пользователей? Ознакомьтесь с практическими шагами в статье.

 

Распространенные ошибки ⚠️

  1. Кэширование часто меняющихся файлов без версионирования. Если вы поставите max-age=1 год на style.css и измените дизайн, пользователи будут видеть старый дизайн еще год. Решение: меняйте имя файла при обновлении (например, style.v2.css или style.css?v=2).
  2. Использование public для приватных данных. Никогда не используйте public для страниц, где есть личные данные пользователя, иначе они могут остаться в кэше публичного прокси.
  3. Отсутствие заголовков. Если вы не пошлете никаких заголовков, браузер сам попытается “угадать”, как кэшировать контент (Heuristic Caching), и результат может быть непредсказуемым.

 

Вывод: баланс между скоростью и актуальностью

По моему мнению, настройка заголовков кэширования — это искусство найти баланс. Вы хотите, чтобы пользователь загружал как можно меньше данных (долгий кэш), но при этом всегда видел актуальную версию сайта.

Мой рецепт прост: “агрессивно” кэшируйте статику (картинки, шрифты) с долгим сроком жизни, используйте версионирование файлов для CSS/JS, и будьте осторожны с кэшированием HTML-страниц, используя no-cache для динамического контента.

 

Категорії:

Перегляди 869
розкажіть друзям:

Напишіть тут свою думку/питання

Ваша пошта не публікуватиметься. Обов’язкові поля позначені *