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 за споделени (shared) кешове, без да засяга браузърите

Какво е 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 определя три нива на кеширане: браузър/приложение (private cache), прокси сървъри (shared cache) и CDN (distributed cache). Всяко ниво интерпретира директивите по свой начин.

Неправилната конфигурация на 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 за shared cache (прокси, 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 задължително проверете при originmax-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 MB кеш и презаписва 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 позволява на потребителя да вижда остарял кеш (stale), докато приложението зарежда пресни данни на заден план. Това дава ефект на незабавен отговор: потребителят вижда съдържанието веднага, а след секунда то се актуализира. Поддържа се от 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 минута stale
API: потребителски данниprivate, max-age=601 минута, само за конкретния потребител
API: чувствителни данниno-storeПълна забрана на кеширането
HTML странициno-cache, must-revalidateПроверка при всяка заявка, 304 при липса на промяна

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

Дебагване на кеширането

За да проверите правилността на 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 — само за shared cache (прокси, 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 за shared cache, полезен за разделяне на политиките за браузър/CDN
  • stale-while-revalidate — показване на остарял кеш с актуализация на заден план за незабавен UX
  • Препоръка — конфигурирайте Cache-Control за всеки тип ресурс на сървъра и в мобилния HTTP клиент

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също