Cache-Control — що це таке, директиви та керування кешуванням

Автор: IT Sectr Опубліковано: 2026-03-09 Час читання: 9 хв

Cache-Control — це HTTP-заголовок, який визначає правила кешування ресурсів на стороні клієнта, проксі-серверів та CDN за допомогою набору директив. На відміну від застарілого заголовка Expires, Cache-Control підтримує десятки комбінацій: max-age задає час життя в секундах, private та public керують доступністю кешу, no-cache та no-store — примусовою перевіркою. За даними Google Web Dev (2025), правильна конфігурація Cache-Control може скоротити час завантаження сторінок на 50-80% для повторних відвідувань. Це робить заголовок критично важливим для продуктивності веб-та мобільних додатків.

Головне

  • Cache-Control — HTTP-заголовок з директивами, що керують кешуванням на клієнті, проксі та CDN
  • max-age — ключова директива, що задає час життя ресурсу в секундах без повторної перевірки
  • private vs public — private дозволяє кеш лише на клієнті, public — також на проксі та CDN
  • no-cache vs no-store — no-cache вимагає перевірки перед використанням, no-store повністю забороняє кеш
  • s-maxage — переопреділює max-age для спільних кешів, не впливаючи на браузери

Що таке Cache-Control?

Cache-Control — це HTTP-заголовок, стандартизований в HTTP/1.1 (RFC 7234), який дозволяє серверу вказати, як і протягом якого часу клієнти, проксі та CDN можуть кешувати відповідь. На відміну від Expires (HTTP/1.0), Cache-Control використовує директиви — текстові команди, що комбінуються через кому: Cache-Control: public, max-age=3600, must-revalidate. Заголовок надає тонкий контроль над кожною ланкою ланцюжка кешування.

Кешування — один із фундаментальних механізмів продуктивності веб-та мобільних додатків. Без нього кожен запит користувача йшов би безпосередньо до сервера, викликаючи надмірне навантаження та затримки. Cache-Control визначає три рівні кешування: браузер/додаток (приватний кеш), проксі-сервери (спільний кеш) та CDN (розподілений кеш). Кожен рівень інтерпретує директиви по-різному.

Неправильне налаштування Cache-Control — одна з найчастіших причин проблем з продуктивністю. Надмірно агресивне кешування призводить до того, що користувачі бачать застарілі дані. Надто слабке кешування призводить до надмірних запитів до сервера та повільного завантаження. За даними Akamai (2025), оптимізація Cache-Control для статичного контенту знижує навантаження сервера на 70-90% і покращує час завантаження на 40-60% для мобільних користувачів.

Історія заголовка

Cache-Control з'явився в HTTP/1.1 (RFC 2616, 1999) як заміна Expires. Expires мав фундаментальну проблему: він використовував абсолютну дату, яка залежала від часових поясів сервера та клієнта. Cache-Control вирішив цю проблему, перейшовши на відносний час (max-age в секундах від моменту отримання відповіді). Пізніше в RFC 7234 (2014) були додані нові директиви: immutable для статичних ресурсів, stale-while-revalidate та stale-if-error для відстроченої перевірки.

Директиви Cache-Control

Cache-Control включає понад 10 директив, розділених на три групи: директиви запиту (клієнт → сервер), директиви відповіді (сервер → клієнт) та розширення. На практиці в мобільній розробці використовуються 6-7 основних директив відповіді, що охоплюють 95% сценаріїв кешування. Розглянемо кожну з прикладами та рекомендаціями.

ДирективаЗначенняПриклад
max-ageЧас життя в секундах від моменту відповідіmax-age=3600 — 1 година
s-maxagemax-age для спільного кешу (проксі, CDN)s-maxage=86400 — 1 день для CDN
publicДозволяє кешування всім (включно з проксі)public, max-age=3600
privateДозволяє кеш лише для браузера/додаткаprivate, max-age=600
no-cacheНе використовувати без перевірки (304 обов’язковий)no-cache
no-storeПовністю заборонити кешуванняno-store
must-revalidateПісля max-age обов’язково перевіряти на джереліmax-age=3600, must-revalidate
immutableРесурс не зміниться (для версіонованих статичних ресурсів)max-age=31536000, immutable

max-age — найважливіша директива. Вона забороняє клієнту звертатися до сервера протягом зазначеного часу. Для статичних ресурсів (CSS, JS, зображення) max-age зазвичай встановлюють від 1 дня до 1 року. Для відповідей API — від 0 секунд (дані завжди свіжі) до 5-10 хвилин (довідкові дані). s-maxage дозволяє встановити різний час життя для CDN та браузера: CDN зберігає копію 1 день, браузер — 1 годину.

no-cache vs no-store

Ці дві директиви часто плутають. no-cache не забороняє кешування — він вимагає перевіряти кешовану копію при кожному використанні через умовний запит (If-Modified-Since або If-None-Match). Якщо сервер відповідає 304 — клієнт використовує кеш. Якщо 200 — оновлює. no-store ж повністю забороняє зберігати відповідь в будь-якому кеші, включно з диском та оперативною пам’яттю. Використовуйте no-store лише для чутливих даних — токени, платіжні дані, особисті документи.

Cache-Control vs Expires

Заголовок Expires (HTTP/1.0) також вказує час життя ресурсу, але використовує абсолютну дату: Expires: Thu, 03 Jul 2026 12:00:00 GMT. Cache-Control max-age використовує відносний час від моменту отримання відповіді. Різниця критична для розподілених систем: якщо сервер та клієнт знаходяться в різних часових поясах, Expires може бути проінтерпретований неправильно. Cache-Control не має цієї проблеми — 3600 секунд завжди 3600 секунд.

Коли обидва заголовки присутні, Cache-Control має пріоритет над Expires. Це визначено в RFC 7234: «Якщо відповідь містить поле Cache-Control з директивою max-age, отримувач повинен ІГНОРУВАТИ поле Expires.» На практиці рекомендується не повертати Expires для сучасних клієнтів, оскільки Cache-Control покриває всі сценарії Expires. Однак для зворотньої сумісності зі старими проксі та браузерами можна повертати обидва заголовки.

Expires зберігся в основному для статичного контенту на Nginx та Apache — ці сервери автоматично додають обидва заголовки. Якщо ваш проект зустрічає Expires без Cache-Control, замініть його на Cache-Control з max-age: точність керування кешем підвищується, а залежність від часового поясу усувається. Для міграції достатньо налаштувати сервер на додавання Cache-Control замість Expires.

nginx
# Nginx: Cache-Control для статичних файлів
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 30d;
    add_header Cache-Control "public, immutable, max-age=2592000";
}

# Різні політики для різних типів контенту
location /api/config {
    expires -1;
    add_header Cache-Control "no-cache, must-revalidate";
}

location /api/static-data {
    expires 5m;
    add_header Cache-Control "public, max-age=300";
}

У конфігурації Nginx статичним файлам (CSS, JS, зображення) встановлюється Cache-Control на 30 днів з атрибутом immutable — цей атрибут повідомляє браузеру, що ресурс ніколи не змінюється за цією URL (версіонування через хеш у назві файлу). API-ендпоінти використовують no-cache для динамічних даних та public з коротким max-age для довідкових даних — списків, які часто запитуються та рідко змінюються.

Кешування в мобільних додатках

У мобільних додатках Cache-Control відіграє особливу роль через обмеження мобільних мереж: висока затримка, нестабільне з’єднання, ліміти трафіку. Правильне кешування дозволяє показувати користувачу дані миттєво, навіть офлайн, та оновлювати їх у фоні. OkHttp на Android та URLSession на iOS мають вбудовані системи кешування, що враховують Cache-Control.

OkHttp використовує CacheInterceptor, який читає Cache-Control з відповіді та автоматично керує кешуванням. Якщо сервер повернув Cache-Control: max-age=3600, OkHttp не буде робити запит до сервера протягом години. Після закінчення max-age OkHttp надсилає умовний запит з If-Modified-Since та If-None-Match. Налаштування кешу в OkHttp: OkHttpClient.Builder().cache(Cache(directory, maxSize)).

kotlin
fun createCachedClient(cacheDir: File): OkHttpClient {
    return OkHttpClient.Builder()
        .cache(Cache(cacheDir, 10L * 1024 * 1024))
        .addNetworkInterceptor { chain ->
            val response = chain.proceed(chain.request())
            response.newBuilder()
                .header("Cache-Control",
                    "public, max-age=300")
                .removeHeader("Pragma")
                .build()
        }
        .build()
}

Код створює OkHttpClient з кешем на 10 МБ та переопреділює Cache-Control через NetworkInterceptor. Якщо сервер не повертає Cache-Control або використовує Expires, інтерцептор додає public, max-age=300 (5 хвилин). Інтерцептор видаляє застарілий заголовок Pragma (HTTP/1.0) для сумісності. Кешування на iOS працює аналогічно через URLCache.shared з налаштуваннями memoryCapacity та diskCapacity.

Офлайн-режим та stale-while-revalidate

Директива stale-while-revalidate дозволяє показувати користувачу застарілий кеш, поки додаток у фоні завантажує свіжі дані. Це дає ефект миттєвої відповіді: користувач бачить контент відразу, а через секунду він оновлюється до актуальної версії. Підтримується OkHttp починаючи з версії 3.10 та URLCache на iOS 14+. Приклад: Cache-Control: max-age=3600, stale-while-revalidate=300 — 1 година свіжого кешу, потім 5 хвилин показу застарілих даних з фоновим оновленням.

Приклади налаштування Cache-Control

Різні типи ресурсів потребують різних стратегій кешування. Розглянемо оптимальні конфігурації для типових сценаріїв у мобільній розробці. Для статичного контенту з хешем у назві файлу (bundle.abc123.js) можна встановлювати max-age до 1 року з immutable. Для списків API, які рідко оновлюються (довідники, категорії), — max-age від 5 хвилин до 1 години з stale-while-revalidate.

Тип ресурсуCache-ControlПояснення
Версіоновані статичні ресурсиpublic, max-age=31536000, immutable1 рік, файли не змінюються (хеш в URL)
Неверсіоновані статичні ресурсиpublic, max-age=86400, must-revalidate1 день з примусовою перевіркою після
API: довідкові даніpublic, max-age=600, stale-while-revalidate=6010 хвилин кешу + 1 хвилина застарілих даних
API: дані користувачаprivate, max-age=601 хвилина, лише для конкретного користувача
API: чутливі даніno-storeПовна заборона кешування
HTML-сторінкиno-cache, must-revalidateПеревірка при кожному запиті, 304 при незмінності

Важливо пам’ятати про безпеку: для відповідей, що містять персональні дані користувача, завжди встановлюйте private. Без цієї директиви публічний проксі (наприклад, корпоративний) може закешувати відповідь та надати їі іншому користувачу. Для токенів автентифікації та платіжної інформації використовуйте no-store — навіть приватний кеш не повинен зберігати ці дані на диску.

Налагодження кешування

Для перевірки правильності Cache-Control використовуйте заголовок Age (скільки секунд кеш зберігається) та X-Cache (hit/miss на CDN). У браузері — вкладка Network, колонка Size показує «from disk cache» або «304 Not Modified». Якщо ресурс повинен кешуватися, але завантажується кожного разу, перевірте, чи не додає сервер Cache-Control: no-cache або Pragma: no-cache разом з вашими директивами.

Часто запитувані питання

У чому різниця між max-age та s-maxage?

max-age діє для всіх кешів (включно з браузерами), s-maxage — лише для спільних кешів (проксі, CDN). Якщо вказано s-maxage, CDN ігнорує max-age та використовує s-maxage. Це дозволяє задати різний час життя для браузера та CDN.

Чи можна скасувати кешування після відправлення Cache-Control?

Ні, після відправлення відповіді з max-age клієнт не робитиме запит до закінчення таймера. Для негайної інвалідації кешу потрібно змінити URL ресурсу (додати версію/хеш) та розіслати push-повідомлення або WebSocket-повідомлення для примусового скидання.

Що таке директива immutable?

Директива immutable (RFC 8246) повідомляє браузеру, що ресурс ніколи не зміниться за цією URL. Браузер навіть не намагається зробити умовний запит при оновленні сторінки — він використовує кеш до закінчення max-age. Працює лише з версіонованими файлами.

Як Cache-Control впливає на SEO?

Googlebot враховує Cache-Control: довге кешування прискорює повторне сканування. noindex з швидким кешем нормально. no-store може уповільнити індексацію, оскільки Googlebot буде завантажувати сторінку з нуля кожного разу. Занадто короткий max-age збільшує навантаження сервера під час сканування.

Як налаштувати Cache-Control в Express.js?

Через helmet або middleware: res.set('Cache-Control', 'public, max-age=3600'). Для статичних файлів використовуйте express.static з параметром maxAge: express.static('public', {maxAge: '1y'}). Для динамічних маршрутів — індивідуально в кожному обробнику.

Підсумки

  • Cache-Control — основний HTTP-заголовок для керування кешем з гнучкою системою директив
  • max-age — час життя в секундах від моменту відповіді; ключова директива для всіх сценаріїв кешування
  • private vs public — private лише для клієнта, public для проксі та CDN; впливає на безпеку даних
  • no-cache вимагає перевірки, no-store повністю забороняє кеш; різні призначення, не плутайте
  • s-maxage — переопреділює max-age для спільних кешів, корисно для розділу політик браузер/CDN
  • stale-while-revalidate — показ застарілого кешу з фоновим оновленням для миттєвої UX
  • Рекомендація — налаштуйте Cache-Control для кожного типу ресурсів на сервері та в мобільному HTTP-клієнті

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також