Technikai

Cache-Control és Vary fejlécek helyes beállítása magyar tárhelyen

Cache-Control, ETag, Last-Modified és Vary fejlécek helyes beállítása magyar tárhelyen: konkrét .htaccess és nginx példa, curl -I ellenőrzés, tipikus hibák.

Scheo · 2026-09-04 · olvasási idő ~10 perc · Szerző: Schmidt Péter

A lényeg dióhéjban: A Cache-Control mondja meg, meddig tárolható a válasz, az ETag és a Last-Modified azt, hogyan lehet olcsón újraellenőrizni, a Vary pedig azt, mitől függ a válasz. A legtöbb magyar kkv-oldalon nem a cache hiányzik, hanem a plugin, a szerver és a CDN egyszerre állítja ugyanazt a fejlécet.

A gyorsítótárazás azon ritka webes területek egyike, ahol néhány jól megírt fejléc-sor többet ér bármelyik gyorsító pluginnál. És azon területek egyike is, ahol néhány rosszul megírt sor kioltja egymást, te pedig csak annyit látsz, hogy az oldal hol gyors, hol nem, a látogató meg a múlt heti CSS-t kapja egy friss HTML-hez. Ebben a cikkben végigmegyünk azon, mit csinál valójában a négy fontos fejléc, milyen értéket érdemes adni nekik fájltípusonként, és hogyan ellenőrzöd, mi jött vissza ténylegesen.

Cache-Control és Vary fejlécek helyes beállítása magyar tárhelyen
Cache-Control és Vary fejlécek helyes beállítása magyar tárhelyen

Mit jelent a Cache-Control a gyakorlatban?

A Cache-Control az a fejléc, amivel a szerver megmondja a böngészőnek és a köztes gyorsítótáraknak (CDN, proxy), hogy a választ szabad-e eltárolni, meddig, és kinek. Hivatalosan igazolt: a viselkedést az RFC 9111 írja le, és minden mai böngésző eszerint jár el.

A gyakorlatban ezt a hat irányelvet fogod használni:

A leggyakoribb félreértés a no-cache és a no-store összekeverése. Ha bejelentkezett felhasználó adatairól van szó, a no-cache önmagában kevés lehet, mert a válasz ott ül a lemezen. Ha viszont mindenre no-store-t teszel, eldobod a feltételes kérések előnyét is.

Mi a különbség az ETag és a Last-Modified között?

Mindkettő ugyanarra való: ha a böngésző cache-ében lejárt egy fájl, ne kelljen újra letölteni, ha közben nem változott. A Last-Modified egy időbélyeg, a böngésző If-Modified-Since fejléccel kérdez vissza. Az ETag a tartalom ujjlenyomata, a visszakérdezés If-None-Match fejléccel megy. Ha nincs változás, a szerver 304-et küld törzs nélkül, tehát a sávszélesség megspórolva, de egy kör-idő azért elmegy.

Az ETag pontosabb, mert a másodperc alatti változást és a visszaállított régi verziót is elkapja. Van viszont egy klasszikus buktatója: hivatalosan igazolt, hogy az Apache alapértelmezésben az inode-ot is beleszámolja az ETag értékébe, így két szerver ugyanarra a fájlra más ETaget ad. Egy gépen ez nem gond, load balancer mögött viszont folyamatos újraletöltés lesz belőle. A megoldás egy sor: FileETag MTime Size.

Saját tapasztalat: magyar megosztott tárhelyen ez ritkán számít, mert egy gépen fut minden. Ott inkább az fordul elő, hogy egy optimalizáló plugin kikapcsolja az ETaget (mert valamelyik régi útmutató azt írta, hogy "felesleges fejléc"), és utána a nagy képek 304 helyett minden lejáratkor újra letöltődnek.

Mire való a Vary fejléc, és miért veszélyes?

A Vary azt mondja meg a gyorsítótárnak, hogy a válasz mely kérés-fejlécektől függ. Ha Vary: Accept-Encoding van rajta, a cache külön tárolja a gzip, a brotli és a tömörítetlen változatot, és a megfelelőt adja vissza. Ez helyes és szükséges, mindenhol legyen rajta a tömörített tartalmon.

A baj ott kezdődik, amikor a Vary olyan fejlécre mutat, aminek rengeteg különböző értéke van. A User-Agent gyakorlatilag végtelen sok variációt vesz fel, a Cookie pedig minden egyes látogatónál más. Ilyenkor a cache elvileg működik, csak minden bejegyzés egyszer használatos lesz. Hivatalosan igazolt: a Google a dinamikus kiszolgáláshoz (ugyanaz az URL, más HTML mobilon) valóban a Vary: User-Agent használatát javasolja, de ez a köztes gyorsítótárak számára jelzés, nem ajándék. Ha nem csinálsz dinamikus kiszolgálást, ne tedd ki.

Melyik fájltípusnál milyen értéket állíts?

Hash-elt nevű statikus fájl

Ha a fájlnévben benne van a tartalom ujjlenyomata (app.4f3a1b.css), a fájl tartalma soha nem fog megváltozni, mert változáskor új név keletkezik. Itt nyugodtan mehet a maximum:

Cache-Control: public, max-age=31536000, immutable

Nem hash-elt statikus fájl

Feltöltött képek, régi témafájlok, logo.png. Ezeket bármikor felülírhatják ugyanazon a néven, ezért itt egy hét és egy hónap közötti érték az ésszerű, ETaggel együtt:

Cache-Control: public, max-age=604800

HTML anonim látogatónak

A HTML tartalma bármikor változhat, ezért a böngészőben ne álljon sokáig, a CDN-ben viszont nyugodtan:

Cache-Control: public, max-age=0, s-maxage=600, stale-while-revalidate=60

Bejelentkezett felhasználó, kosár, fiókoldal

Itt a személyes adat kiszivárgásának kockázata nagyobb, mint a sebesség nyeresége. A WooCommerce kosár, pénztár, fiók és a wp-admin soha ne kerüljön megosztott cache-be:

Cache-Control: private, no-store, max-age=0

Hogy néz ki ez konkrétan .htaccess-ben?

Apache-on a mod_expires és a mod_headers kell hozzá. Egy visszafogott, működő minta:

<IfModule mod_headers.c>

  FileETag MTime Size

  <FilesMatch "\.(css|js|woff2)$">

    Header unset Cache-Control

    Header set Cache-Control "public, max-age=31536000, immutable"

    Header append Vary Accept-Encoding

  </FilesMatch>

  <FilesMatch "\.(jpg|jpeg|png|webp|avif|svg)$">

    Header set Cache-Control "public, max-age=604800"

  </FilesMatch>

</IfModule>

Két apróság, ami sokba kerül. A Header unset a set előtt azért kell, mert különben két Cache-Control fejléc megy ki, és a kliens ezeket egyetlen vesszős listaként olvassa. Az append pedig azért jobb a Varynál, mint a set, mert nem törli, amit a PHP vagy a plugin már odaírt. Az immutable irányelvet csak akkor tedd ki, ha tényleg hash van a fájlnévben.

És nginx-en?

location ~* \.(css|js|woff2)$ {

  add_header Cache-Control "public, max-age=31536000, immutable" always;

  add_header Vary Accept-Encoding always;

}

location ~* ^/(kosar|penztar|fiok|wp-admin) {

  add_header Cache-Control "private, no-store" always;

}

Hivatalosan igazolt buktató: az nginx add_header direktívái nem öröklődnek lefelé, ha a gyerek blokkban is van legalább egy add_header. Tehát ha a szerver szintjén beállítottad a biztonsági fejléceket, majd egy location blokkba beírsz egy Cache-Controlt, a többi fejléc abban a blokkban némán eltűnik. Ez az egyik leggyakoribb ok, amiért egy audit szerint "hiányzik a HSTS", pedig ott van, csak nem a képeken.

Hogyan ellenőrzöd, mi jött vissza ténylegesen?

Amit beállítottál, és amit a látogató kap, két külön dolog. Ellenőrzés nélkül csak feltételezel. A leggyorsabb út a parancssor:

curl -sI https://pelda.hu/ | grep -i -E 'cache-control|etag|last-modified|vary|age|x-cache'

Amit érdemes megnézni, sorrendben:

  1. Van-e két Cache-Control sor a válaszban. Ha igen, két réteg állítja, és ezt kell először rendbe tenni.
  2. Futtasd le kétszer egymás után. Ha a CDN dolgozik, az Age érték nő, a szolgáltató saját fejléce pedig MISS-ről HIT-re vált.
  3. Kérd le tömörítéssel: curl -sI -H 'Accept-Encoding: gzip' https://pelda.hu/. Ha itt más a válasz, de nincs Vary: Accept-Encoding, sérült válasz mehet ki egyes klienseknek.
  4. Próbáld ki a feltételes kérést: másold ki az ETag értékét, és küldd vissza -H 'If-None-Match: "..."' fejléccel. 304-et kell kapnod.
  5. Nézd meg bejelentkezett állapotot is: curl -sI --cookie 'wordpress_logged_in_x=1' https://pelda.hu/kosar/. Itt private vagy no-store kell.

Böngészőben a Network fülön kapcsold ki a Disable cache jelölőt (különben pont azt méred, amit kizártál), tölts újra, és nézd a Size oszlopot: a (disk cache) és (memory cache) bejegyzések el sem hagyták a gépet, a 304-es sorok visszakérdeztek, a 200-asok újra letöltődtek. Egy sorra kattintva a Response Headers alatt ott a teljes igazság.

Mikor okoz a túl hosszú max-age régi CSS-t a látogatónál?

Akkor, ha a fájl neve nem változik, de a tartalma igen. Beállítasz egy éves max-age-et a style.css-re, két hét múlva átszínezed a gombokat, és a visszatérő látogató a régi fájlt látja egy új HTML-hez. Nem tudsz mit tenni: a böngészőbe kihelyezett választ nem lehet visszahívni, a Ctrl+F5 pedig csak azoknál segít, akik megnyomják, és az immutable irányelv kifejezetten arra való, hogy sima újratöltésnél se kérdezzen vissza.

A kimenet két irány. Vagy verziózod a fájlnevet (a WordPress ezt a ?ver= paraméterrel próbálja), vagy rövidebb max-age-et adsz a nem hash-elt fájloknak. Fontos részlet: a lekérdezési paraméterrel való cache-törés a böngészőnél jó eséllyel működik, de több CDN alapértelmezetten nem veszi bele a query stringet a cache-kulcsba, tehát az él-oldali példány marad a régi. Ha CDN-t használsz, a valódi fájlnév cseréje a megbízható út.

Miért esik szét a CDN-találati arány a Vary miatt?

Egy CDN úgy dönt, hogy két kérés ugyanaz-e, hogy összerakja a cache-kulcsot: URL, kérési metódus, plusz azok a fejlécek, amiket a Vary megnevez. Ha kiteszed a Vary: User-Agent fejlécet, minden böngészőverzió, minden telefon-modell és minden bot külön bejegyzést kap ugyanarra az URL-re. Az arány nem nullára esik, hanem valami látszólag működő, alacsony számra, és nehéz észrevenni, mert a HIT sorok ott vannak, csak kevesen.

A Vary: Cookie még durvább, mert az analitikai és a hozzájárulás-kezelő sütik miatt szinte minden látogatónak más a Cookie fejléce. Szakmai feltételezés: ez a legtöbb magyar oldalon nem szándékos beállítás, hanem egy session-t indító PHP-részlet vagy egy nyelvváltó plugin mellékterméke. Hivatalosan igazolt: több nagy CDN dokumentációja leírja, hogy a Vary értékei közül csak korlátozott körre (jellemzően az Accept-Encodingra) van tekintettel, tehát a fejléc hatása szolgáltatónként eltér. Ha személyre szabott HTML-t adsz vissza, a helyes válasz nem a Vary: Cookie, hanem az, hogy azt az útvonalat nem engeded megosztott cache-be.

Mi a valódi baj a legtöbb magyar kkv-oldalon?

Saját nézőpont, saját tapasztalat: ezeknél az oldalaknál szinte soha nem a cache hiánya a probléma. Cache van, méghozzá három is. Van egy gyorsító plugin, ami a telepítéskor beleírt egy szabályblokkot az .htaccess fájlba. Van a tárhely saját szerver-oldali gyorsítója, aminek megvan a maga fejléc-politikája. És van egy CDN, aminek a felületén valaki bepipálta a böngésző-cache élettartamát is. Mindhárom ugyanarra a fájlra ugyanazt a fejlécet állítja, más értékkel.

Az eredmény nem az, hogy "valamelyik nyer". Az eredmény két Cache-Control sor a válaszban, amiket a kliens egyetlen listaként olvas, és a szigorúbb irányelvet veszi figyelembe. Ha a plugin egy évet mond, a CDN meg no-cache-t, akkor a no-cache érvényesül, és pont az az egy év veszik el, amiért az egészet csináltad. Fordítva is megvan: egy hosszú max-age megmarad ott, ahol a szerver már rég rövidebbet szeretne.

A javítás sorrendje ezért nem az, hogy "állítsuk be jól". Először le kell zárni, hogy melyik réteg felel a fejlécekért, a másik kettőt kikapcsolni, és csak utána hangolni. Egy réteg, egy igazság. Szakmai feltételezés: a hazai megosztott tárhelyek egy részén a szerver-oldali gyorsító alapból aktív, és nem is minden felületen látszik, ezért érdemes a tárhelyszolgáltatót megkérdezni, mielőtt az .htaccess-ben keresed a hibát.

Milyen ellenőrzőlistán érdemes végigmenni?

  1. Nézd meg curl-lel, hány Cache-Control sor jön vissza a főoldalra és egy CSS-fájlra.
  2. Írd össze, hány réteg állít fejlécet: plugin, szerver konfiguráció, CDN szabály.
  3. Válaszd ki azt az egyet, ahol a beállítás verziókövethető és látható, a másik kettőben kapcsold ki a fejléc-írást.
  4. Statikus fájlokra adj hosszú max-age-et, de immutable-t csak hash-elt névnél.
  5. HTML-re rövid böngésző-oldali és hosszabb CDN-oldali élettartamot állíts.
  6. A kosarat, pénztárat, fiókot és az admin felületet zárd ki a megosztott cache-ből.
  7. Vary fejlécen csak Accept-Encoding legyen, hacsak nincs dinamikus kiszolgálásod.
  8. Deploy után futtasd le újra a curl-ellenőrzést, és nézd meg, hogy a régi fájlnév tényleg lecserélődött-e.

Számít ez a keresők és az AI-válaszmotorok szempontjából?

Közvetlen rangsorolási hatást senki nem ígérhet, és a jó cache-fejléc önmagában nem garantál jobb helyezést. Ami mérhető: a helyesen kezelt feltételes kérés (ETag vagy Last-Modified plusz 304-es válasz) csökkenti a szerver terhelését, és hivatalosan igazolt módon takarékosabbá teszi a Google újrabejárását is, mert a változatlan oldalakat nem kell újra letöltenie. Az AI-crawlerek és a válaszmotorok forgalma ugyanezen a csatornán jön be, tehát a stabil ETag és a rendezett fejléc-politika segítheti azt, hogy a robotok terhelése ne menjen a látogatók sebességének rovására. A gyorsabb betöltés pedig a felhasználói mutatókon keresztül, közvetve javíthatja az oldal helyzetét, de ez nem lineáris összefüggés.

Források és további olvasnivalók

A legfontosabbak
  • Hash-elt nevű statikus fájlnál hosszú max-age és immutable, HTML-nél rövid vagy nulla böngésző-oldali élettartam, bejelentkezett felhasználónál private vagy no-store.
  • A Vary: User-Agent és a Vary: Cookie a CDN-találati arányt tudja szétaprózni, mert minden változatot külön bejegyzésként kezel.
  • A túl hosszú max-age nem visszavonható: nem hash-elt CSS-nél csak a fájlnév cseréje segít, a hard refresh nem éri el az összes látogatót.
  • Amit beállítottál, és amit a látogató kap, két külön dolog: curl -I vagy a böngésző Network füle nélkül csak feltételezel.
  • Egy fejlécet egy rétegben állíts be, a másik kettőt kapcsold ki, különben egymást írják felül.

Gyakori kérdések

Mi a különbség a no-cache és a no-store között?

A no-cache engedi a tárolást, de minden felhasználás előtt vissza kell kérdezni a szerverhez, hogy változott-e a tartalom. A no-store egyáltalán nem engedi eltárolni a választ sem a böngészőben, sem a CDN-ben. Személyes adatot tartalmazó oldalnál (kosár, fiók, admin) a no-store a helyes választás.

Miért látja a látogató a régi CSS-t, ha már feltöltöttem az újat?

Mert a régi fájl a böngészője cache-ében ül, és a hosszú max-age miatt meg sem kérdezi a szervert. Ha a fájlnév nem változott, ezt utólag nem tudod visszahívni. Két megoldás van: cseréld a fájlnevet (verziószám vagy hash a névben), vagy adj rövidebb max-age-et a nem verziózott fájloknak. A ?ver= paraméter a böngészőnél jó eséllyel működik, de több CDN nem veszi bele a cache-kulcsba.

Kell ETag, ha van Last-Modified?

Nem kötelező mindkettő, de nem is árt. Az ETag pontosabb, mert a másodpercen belüli és a visszaállított változást is elkapja, a Last-Modified viszont olcsóbb és minden szerveren ott van. Ha több szerver szolgálja ki ugyanazt a fájlt, az Apache alapértelmezett ETag-számítását állítsd át (FileETag MTime Size), különben gépenként más értéket kapsz.

Miért rossz a Vary: User-Agent?

Mert a CDN a Vary-ban felsorolt fejlécek szerint készít külön cache-bejegyzést, a User-Agent értéke pedig gyakorlatilag minden eszközön más. Így ugyanarra az URL-re több ezer bejegyzés keletkezik, amiből alig lesz találat. Csak akkor tedd ki, ha tényleg dinamikus kiszolgálást használsz, tehát ugyanazon az URL-en más HTML megy mobilra és asztali gépre.

Hogyan tudom megnézni, mit küld ténylegesen a szerverem?

Parancssorból: curl -sI https://pelda.hu/ és nézd meg a Cache-Control, ETag, Last-Modified, Vary és Age sorokat. Futtasd le kétszer, hogy lásd, nő-e az Age (ez a CDN-találatot jelzi). Böngészőben a Network fülön kapcsold ki a Disable cache jelölőt, tölts újra, és a Size oszlopban látod, mi jött cache-ből, mi kapott 304-et, és mi töltődött le újra.

Elég egy gyorsító plugin a WordPressben, vagy kell szerver-oldali beállítás is?

A plugin önmagában sokszor elég, a gond akkor kezdődik, ha a plugin, a tárhely saját gyorsítója és a CDN egyszerre állítja ugyanazt a fejlécet. Ilyenkor két Cache-Control sor megy ki, és a szigorúbb irányelv érvényesül, ami nem feltétlenül az, amit szerettél volna. Válaszd ki azt az egy réteget, ahol a beállítás látható és követhető, a másik kettőben pedig kapcsold ki a fejléc-írást.

Források és további olvasnivalók

Ezen az oldalon a hivatalosan igazolt információt elsődleges forrásokból építjük fel; a saját tapasztalatot és a szakmai becslést mindig külön jelöljük a szövegben.

Kapcsolódó

Amikor az AI-botok megterhelik a szervert: mit tegyél

Kapcsolódó

Ügynöki (agentic) böngészés: amikor nem ember nyitja meg az oldalad

Helyi szolgáltatás a környékeden

Országosan dolgozunk, online és személyesen. Válaszd ki a városodat, és nézd meg, hogyan segítünk helyben:

Online marketing & AI SEO SzékesfehérvárOnline marketing & AI SEO BudapestOnline marketing & AI SEO VeszprémOnline marketing & AI SEO DunaújvárosOnline marketing & AI SEO GyőrOnline marketing & AI SEO DebrecenOnline marketing & AI SEO SzegedOnline marketing & AI SEO MiskolcOnline marketing & AI SEO PécsOnline marketing & AI SEO KecskemétOnline marketing & AI SEO NyíregyházaOnline marketing & AI SEO SzombathelyOnline marketing & AI SEO SzolnokOnline marketing & AI SEO TatabányaOnline marketing & AI SEO KaposvárOnline marketing & AI SEO BékéscsabaOnline marketing & AI SEO EgerOnline marketing & AI SEO ZalaegerszegOnline marketing & AI SEO SzekszárdOnline marketing & AI SEO Salgótarján

Weboldalkészítés városra bontva

Ha először a honlap kell, itt városonként arról írtunk:

Weboldalkészítés SzékesfehérvárWeboldalkészítés BudapestWeboldalkészítés VeszprémWeboldalkészítés DunaújvárosWeboldalkészítés GyőrWeboldalkészítés DebrecenWeboldalkészítés SzegedWeboldalkészítés MiskolcWeboldalkészítés PécsWeboldalkészítés KecskemétWeboldalkészítés NyíregyházaWeboldalkészítés SzombathelyWeboldalkészítés SzolnokWeboldalkészítés TatabányaWeboldalkészítés KaposvárWeboldalkészítés BékéscsabaWeboldalkészítés EgerWeboldalkészítés ZalaegerszegWeboldalkészítés SzekszárdWeboldalkészítés Salgótarján

15 perces AI-láthatósági gyorselemzés - díjmentesen

Megnézzük három, számodra fontos keresőkérdésnél, hogy megjelenik-e a céged a ChatGPT, a Gemini és a Google AI-válaszaiban, mely versenytársakat ajánlják helyetted, és melyik három területen érdemes először javítani. A weboldaladat előzetesen átnézzük, tehát nem sablonos, automata riportot kapsz.

Adataidat kizárólag a kapcsolatfelvételhez használjuk. Kapcsolat: m@rketinges.hu
💬 Konzultáció