Miért a TTFB az egész webes teljesítmény alapköve?
Ha weboldal-teljesítményről esik szó, a legtöbben rögtön az LCP-re, CLS-re meg az INP-re gondolnak — ezek azok a Core Web Vitals metrikák, amelyeket a Google közvetlenül beleszámít a keresési rangsorolásba. De van egy mérőszám, ami mindezek mögött csendben meghúzódik, és alapvetően meghatározza, milyen gyorsan juthat el bármilyen tartalom a felhasználóhoz: a Time to First Byte, vagyis a TTFB.
Röviden: a TTFB azt az időt méri, ami a böngésző kérésének elküldésétől az első bájt megérkezéséig telik el. Benne van a DNS-feloldás, a TCP-kapcsolat felépítése, a TLS-kézfogás, a szerver feldolgozási ideje és a válasz hálózati átvitelének kezdete. Ha ez az idő magas, minden más — HTML elemzése, CSS letöltése, képek betöltése — késlekedni fog. Nincs mese.
A 2025-ös Web Almanac adatai szerint az asztali webhelyek 55%-a rendelkezik „jó" TTFB-vel (800 ms alatt), 33%-uk „javításra szorul", és 12%-uk „gyenge" minősítést kap. Mobilon a helyzet rosszabb: mindössze 44% éri el a jó szintet, 40% javításra szorul, és 17% gyengén teljesít. Őszintén szólva, ezek a számok évről évre alig javulnak — 2024-ről 2025-re mindössze 1-2 százalékpontos volt az elmozdulás.
Ebben az útmutatóban végigmegyünk a TTFB csökkentésének és a gyorsítótárazási stratégiák optimalizálásának minden lényeges aspektusán. Szerver válaszidő, CDN-stratégiák, HTTP-gyorsítótárazás, edge computing, HTTP/3, Service Worker — mindenre kitérünk, és gyakorlati kódpéldákat is kapunk hozzá.
A TTFB anatómiája: honnan jönnek a milliszekundumok?
Ahhoz, hogy hatékonyan csökkentsük a TTFB-t, először meg kell értenünk, miből áll össze. A Chrome DevTools és a CrUX (Chrome User Experience Report) 2025 februárja óta az LCP-t négy részre bontja, ahol az első komponens maga a TTFB. De a TTFB-t is tovább bonthatjuk:
- DNS-feloldás (DNS Lookup): A domain név IP-címre fordítása. Tipikusan 20-120 ms, de gyorsítótárazatlan esetben akár 200+ ms is lehet.
- TCP-kapcsolat (Connection): A háromfázisú kézfogás a kliens és a szerver között. Távolabbi szerverek esetén 50-150 ms.
- TLS-kézfogás (SSL/TLS Negotiation): A titkosított kapcsolat felépítése. TLS 1.3-mal egy körút, régebbi verziókkal kettő. 30-100 ms.
- Szerver feldolgozási idő (Server Processing): Az a tényleges idő, amíg a szerver összerakja a választ — adatbázis-lekérdezések, szerver oldali renderelés, üzleti logika. Ez szokott a legnagyobb tényező lenni, 50 ms-tól akár több másodpercig.
- Hálózati átvitel (Network Transfer): Az első bájt utazása a szervertől a kliensig. A fizikai távolság és a hálózat aktuális állapota határozza meg.
Minden egyes fázis lehetőséget kínál az optimalizálásra. Nézzük meg egyenként, mit tehetünk.
Szerver oldali optimalizálás: a TTFB legnagyobb ellenségének legyőzése
Adatbázis-lekérdezések gyorsítása
A legtöbb dinamikus weboldalnál a szerver feldolgozási idő oroszlánrésze az adatbázis-lekérdezésekre megy el. Ezt saját tapasztalatból mondom — számtalanszor láttam már, hogy egyetlen rosszul megírt query az egész oldal betöltését megduplázza. Íme a legfontosabb technikák:
-- Lassú lekérdezés: teljes táblaszkennelés
SELECT * FROM articles WHERE status = 'published' ORDER BY created_at DESC;
-- Gyors lekérdezés: összetett index használata
CREATE INDEX idx_articles_status_created ON articles(status, created_at DESC);
SELECT id, title, excerpt, created_at
FROM articles
WHERE status = 'published'
ORDER BY created_at DESC
LIMIT 20;
A legfontosabb szabályok:
- Indexeljünk okosan: Minden WHERE, JOIN és ORDER BY feltételhez legyen megfelelő index. Komplex lekérdezéseknél használjunk összetett (composite) indexeket.
- Kerüljük a SELECT *-ot: Csak azokat az oszlopokat kérjük le, amelyekre tényleg szükségünk van. Ez csökkenti az I/O-t és a memóriahasználatot.
- Használjunk lekérdezés-gyorsítótárat: Redis vagy Memcached segítségével a gyakran ismétlődő lekérdezések eredményeit memóriában tárolhatjuk.
- Készítsünk EXPLAIN ANALYZE elemzést: Rendszeresen nézzük meg a lassú lekérdezéseket, és értsük meg a végrehajtási tervet.
// Node.js példa: Redis gyorsítótár az adatbázis-lekérdezésekhez
const Redis = require('ioredis');
const redis = new Redis();
async function getPublishedArticles(page = 1) {
const cacheKey = `articles:published:page:${page}`;
// Először a gyorsítótárból próbáljuk
const cached = await redis.get(cacheKey);
if (cached) {
return JSON.parse(cached);
}
// Ha nincs a gyorsítótárban, lekérdezzük az adatbázisból
const articles = await db.query(
'SELECT id, title, excerpt, created_at FROM articles WHERE status = $1 ORDER BY created_at DESC LIMIT 20 OFFSET $2',
['published', (page - 1) * 20]
);
// Eredmény mentése a gyorsítótárba (5 perc TTL)
await redis.setex(cacheKey, 300, JSON.stringify(articles));
return articles;
}
Szerver oldali renderelés (SSR) optimalizálása
A modern JavaScript keretrendszerek — Next.js, Nuxt, SvelteKit — szerveroldali renderelése komoly TTFB-növekedést okozhat, ha nem figyelünk oda. A Next.js 15 és a React Server Components (RSC) sokat javítottak ezen, de néhány alapszabályt azért érdemes betartani:
- Streaming SSR használata: A React 18+ és a Next.js App Router támogatja a válasz fokozatos streamelését. Ahelyett, hogy megvárnánk a teljes oldal renderelését, az első bájtot azonnal elküldjük, míg a lassabb komponensek a háttérben készülnek el.
- Statikus generálás (SSG) ahol lehet: Ha az oldal tartalma nem változik minden kérésnél, használjunk statikus generálást. Ez gyakorlatilag nullára csökkenti a szerver feldolgozási idejét.
- Inkrementális statikus regenerálás (ISR): A Next.js ISR funkciója lehetővé teszi, hogy statikus oldalakat a háttérben frissítsünk, anélkül hogy a felhasználóknak várakozniuk kellene.
// Next.js App Router: Streaming SSR Suspense-szel
import { Suspense } from 'react';
// Ez a komponens azonnal renderelődik
function ArticleHeader({ title, author }) {
return (
<header>
<h1>{title}</h1>
<p>Szerző: {author}</p>
</header>
);
}
// Ez a komponens adatbázis-lekérdezést igényel — streameléssel
async function RelatedArticles({ categoryId }) {
const articles = await getRelatedArticles(categoryId);
return (
<aside>
{articles.map(a => <ArticleCard key={a.id} {...a} />)}
</aside>
);
}
export default function ArticlePage({ params }) {
return (
<main>
<ArticleHeader title="TTFB optimalizálás" author="Szerkesztőség" />
<Suspense fallback={<p>Kapcsolódó cikkek betöltése...</p>}>
<RelatedArticles categoryId={params.categoryId} />
</Suspense>
</main>
);
}
DNS optimalizálás és kapcsolatelőkészítés
A TTFB egyik komponense, amelyről sokan megfeledkeznek, a DNS-feloldás. Bár egyetlen DNS-lekérdezés tipikusan 20-120 ms-ot vesz igénybe, egy modern weboldal akár 10-20 különböző domainhez is csatlakozhat (CDN, analitika, hirdetések, harmadik fél szolgáltatások). És mindegyiknek külön DNS-feloldásra van szüksége, ha még nincs a böngésző gyorsítótárában.
DNS-szolgáltató választása
Az autoritatív DNS-szolgáltató megválasztása meglepően nagy hatással lehet a teljesítményre. A hagyományos domain regisztrátorok DNS-szerverei gyakran lassúak és kevés PoP-pal (Point of Presence) rendelkeznek. Érdemes modern alternatívákat nézni:
- Cloudflare DNS: Ingyenes, globális anycast hálózat, tipikusan 10-20 ms válaszidővel. A leggyorsabb autoritatív DNS-szolgáltatók egyike.
- Amazon Route 53: Megbízható, alacsony késleltetés, de fizetős. Remek integráció az AWS ökoszisztémával.
- Google Cloud DNS: Anycast hálózat, 100%-os SLA, szintén fizetős.
DNS prefetching stratégia
A dns-prefetch hint használatával arra utasíthatjuk a böngészőt, hogy a háttérben oldja fel azokat a domaineket, amelyekre az oldalon később szükségünk lesz. Különösen hasznos harmadik fél domaineknél:
<!-- A <head> elején, a lehető legkorábban -->
<link rel="dns-prefetch" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://www.googletagmanager.com">
<link rel="dns-prefetch" href="https://cdn.analytics.example.com">
<!-- A kritikus harmadik fél domainekhez preconnect-et használjunk -->
<!-- Ez a DNS + TCP + TLS kézfogást is elvégzi előre -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://cdn.example.com">
Fontos: a preconnect drágább művelet, mint a dns-prefetch, mert a teljes kapcsolatot felépíti. Ezért csak a legkritikusabb 2-4 domainre használjuk, a többire a dns-prefetch bőven elég. Túl sok preconnect esetén a böngésző erőforrásait feleslegesen foglalja le, ami kontraproduktív.
Hosting és infrastruktúra: az alap, amire minden épül
Mielőtt a CDN-ek és a gyorsítótárazás szofisztikált világába merülnénk, érdemes a legnyilvánvalóbb tényezővel kezdeni: milyen szerveren fut az alkalmazásunk? A hosting típusa drámai hatással van a TTFB-re — és ezt sokan alábecsülik.
Osztott hosting vs. VPS vs. dedikált szerver
Az osztott (shared) hosting a legolcsóbb megoldás, de a legkevésbé kiszámítható is: más webhelyek terhelése közvetlenül befolyásolja a mi válaszidőnket. Egy VPS (Virtual Private Server) garantált CPU- és memória-erőforrásokat kínál, jellemzően 100-300 ms TTFB-vel. A dedikált szerver vagy menedzselt felhőszolgáltatás (AWS, Google Cloud, Azure) a legjobb teljesítményt nyújtja, de természetesen a legdrágább is.
A leggyakoribb hiba, amit tapasztalok: egy egyébként jól optimalizált weboldal osztott hostingon fut, és a TTFB 1500-3000 ms közötti értékeket produkál a szerver túlterheltsége miatt. Ilyenkor hiába optimalizáljuk a CSS-t, a JavaScript-et vagy a képeket — a szerver feldolgozási ideje elnyeli az összes többi megtakarítást.
Szerver lokáció stratégia
A szerver fizikai elhelyezkedése alapvetően befolyásolja a TTFB-t. Minden 1000 km fizikai távolság nagyjából 10 ms hálózati késleltetést jelent (a fénysebesség korlátja miatt — és ezen sajnos nem lehet trükközni). Ha a célközönségünk elsősorban Magyarországon és Közép-Európában van, a szervereinknek Frankfurt, Bécs vagy Varsó környékén érdemes lenniük. Globális közönség esetén a CDN használata elkerülhetetlen.
CDN-stratégiák: a tartalom közelebb hozása a felhasználóhoz
A Content Delivery Network (CDN) az egyik leghatásosabb eszköz a TTFB csökkentésére. A CDN a tartalmat a világ számos pontján elosztott edge szerveren tárolja, így a felhasználó a hozzá legközelebbi szerverről kapja meg a választ. Ez drámaian csökkenti a hálózati késleltetést.
A CDN-gyorsítótárazás rétegei
A modern CDN-architektúra több rétegben működik:
- Edge cache (szélső gyorsítótár): A felhasználóhoz legközelebbi szerver. A Cloudflare például 300+ adatközponttal rendelkezik világszerte.
- Regionális cache (mid-tier): Ha az edge cache-ben nincs meg a tartalom, a regionális szinten próbálkozik. Ez a „tiered caching" vagy „origin shield" technika, és jelentősen növeli a cache találati arányt.
- Origin (eredeti szerver): Csak akkor fordulunk az origin felé, ha a tartalom sehol sincs meg a gyorsítótárban.
Cache-Control fejlécek helyes beállítása
A CDN-gyorsítótárazás hatékonysága nagyban függ a helyesen beállított HTTP Cache-Control fejlécektől. Lássuk a legfontosabb direktívákat és ajánlott beállításaikat:
# Statikus eszközök (CSS, JS, képek) — immutable, hosszú élettartam
# Használjunk verzionált fájlneveket (pl. app.a1b2c3.css)
Cache-Control: public, max-age=31536000, immutable
# HTML oldalak — rövid gyorsítótárazás, revalidálás
Cache-Control: public, max-age=300, s-maxage=3600, stale-while-revalidate=86400
# API válaszok — nem gyorsítótárazható
Cache-Control: private, no-store
# Ritkán változó tartalom (pl. blog posztok)
Cache-Control: public, s-maxage=86400, stale-while-revalidate=604800
Na de mit jelentenek ezek pontosan?
- max-age: Mennyi ideig tekinthetjük a tartalmat frissnek a böngésző gyorsítótárában (másodpercben).
- s-maxage: Ugyanez, de kifejezetten a CDN és más megosztott gyorsítótárak számára. Felülírja a max-age-et ezeknél.
- stale-while-revalidate: Az elavulás után ennyi ideig szolgálhatja ki a gyorsítótár a régi tartalmat, miközben a háttérben frissíti. Ez az egyik leghatásosabb technika a TTFB csökkentésére — komolyan, ha csak egyetlen dolgot csinálsz ebből a cikkből, ez legyen az.
- immutable: Jelzi, hogy a tartalom soha nem fog változni ezen az URL-en. A böngésző nem is próbálja revalidálni.
A stale-while-revalidate stratégia részletesen
A stale-while-revalidate (SWR) az egyik legelegánsabb gyorsítótárazási stratégia, ami tökéletes egyensúlyt teremt a teljesítmény és a frissesség között. Három állapotot különböztetünk meg:
- Friss (Fresh): A
max-agelejárta előtt — a gyorsítótárból azonnal kiszolgáljuk. - Elavult, de felhasználható (Stale): A
max-agelejárt, de astale-while-revalidateidőn belül vagyunk — kiszolgáljuk a régi tartalmat, és a háttérben frissítjük. - Lejárt (Rotten): Mindkét időablak lejárt — a gyorsítótárat figyelmen kívül hagyjuk, és közvetlenül az origin szervertől kérjük a tartalmat.
Konkrét példa: Cache-Control: max-age=60, stale-while-revalidate=300 — ha a tartalom 60 másodpercnél fiatalabb, a gyorsítótárból megy. Ha 60-360 másodperc között van, még mindig a gyorsítótárból szolgáljuk ki, de elindítjuk a háttér-frissítést. 360 másodperc felett pedig kötelezően az origintől kérjük. Egyszerű és elegáns.
Edge Computing: a szerver a felhasználó küszöbén
Az edge computing a CDN koncepcióját egy lépéssel továbbviszi: nemcsak statikus tartalmat tárolunk az edge szerveren, hanem dinamikus logikát is futtatunk ott. Gondoljuk el — az adatbázis-lekérdezések, az API-hívások és akár a szerver oldali renderelés is a felhasználóhoz legközelebbi adatközpontban történhet.
Cloudflare Workers vs. Vercel Edge Functions
2026-ban két platform dominál az edge computing területén:
- Cloudflare Workers: V8 izolátumokat használ, gyakorlatilag nulla hidegindítási idővel (<1 ms). 300+ adatközpont világszerte. 10-30 ms P50 késleltetés globálisan. JavaScript/TypeScript és WebAssembly támogatás.
- Vercel Edge Functions: Szintén V8-alapú futtatókörnyezet, szoros integráció a Next.js-szel. 10-30 ms késleltetés a régión belül, 50-150 ms globálisan az ingyenes/pro csomagban.
// Cloudflare Worker: Edge-szintű gyorsítótárazás egyedi logikával
export default {
async fetch(request, env) {
const url = new URL(request.url);
const cacheKey = new Request(url.toString(), request);
const cache = caches.default;
// Először a Cloudflare edge cache-ből próbáljuk
let response = await cache.match(cacheKey);
if (!response) {
// Ha nincs a cache-ben, lekérdezzük az origint
response = await fetch(request);
// Klónozzuk a választ, mert módosítani fogjuk a fejléceket
response = new Response(response.body, response);
// Cache-Control beállítása az edge számára
response.headers.set(
'Cache-Control',
'public, s-maxage=3600, stale-while-revalidate=86400'
);
// Mentés az edge cache-be
await cache.put(cacheKey, response.clone());
}
return response;
}
};
Edge-szintű A/B tesztelés és személyre szabás
Az edge computing egyik legizgalmasabb felhasználása a felhasználói élmény személyre szabása a TTFB növelése nélkül. Hagyományosan a személyre szabás azt jelentette, hogy a szerver oldali renderelés minden kérésnél egyedi választ generál, ami lehetetlenné tette a gyorsítótárazást. Az edge functionökkel viszont ez megoldható:
- A felhasználó geolokációja alapján lokalizált tartalmat szolgálhatunk ki.
- Cookie vagy fejléc alapján A/B tesztvariánsokat választhatunk.
- Az edge-en dönthetünk, hogy melyik gyorsítótárazott verziót adjuk vissza — anélkül hogy az origin szervert egyáltalán megkérdeznénk.
HTTP/3 és QUIC: a hálózati réteg forradalma
A HTTP/3 — amely a QUIC protokollra épül — 2026-ra komoly teret nyert. A Cloudflare adatai szerint globálisan a forgalom mintegy 35%-a már HTTP/3-on keresztül zajlik. De mit jelent ez konkrétan a TTFB szempontjából?
Miért gyorsabb a HTTP/3?
A HTTP/2 a TCP protokollra épül, ami háromfázisú kézfogást igényel a kapcsolat felépítéséhez, plusz a TLS-kézfogást a titkosításhoz. Ez összesen 2-3 körút (round-trip), mielőtt egyetlen bájt tartalom is elindulna. A HTTP/3 ezzel szemben:
- 0-RTT kapcsolódás: A QUIC protokoll lehetővé teszi, hogy egy korábban meglátogatott szerverhez nulla körutazással csatlakozzunk. Az első kérés már az első csomaggal elindul.
- Nincs head-of-line blocking: TCP-nél ha egy csomag elveszik, az összes többi adatfolyam is várakozni kényszerül. A QUIC-nál minden stream független — egy elveszett csomag csak a saját streamjét lassítja.
- Kapcsolatmigráció: Amikor a felhasználó WiFi-ről mobilhálózatra vált (vagy fordítva), a QUIC-kapcsolat megszakítás nélkül folytatódik. Mobilon ez hatalmas előny.
A gyakorlati hatás mérhető. A Google kutatásai szerint a HTTP/3 átlagosan 8%-kal csökkenti a betöltési időt asztali gépen és 3,6%-kal mobilon. A leglassabb 1%-nál akár 16%-os javulás is mérhető — szélsőséges hálózati körülmények között (magas csomagvesztés, nagy késleltetés) pedig elérheti a 88%-ot.
HTTP/3 engedélyezése
A legtöbb modern CDN (Cloudflare, Fastly, Akamai) alapértelmezetten támogatja a HTTP/3-at. Ha saját szerveren szeretnénk beállítani, az nginx 1.25+ verzió konfigurálható:
# nginx.conf — HTTP/3 engedélyezése
server {
# HTTP/3 (QUIC) a 443-as UDP porton
listen 443 quic reuseport;
# HTTP/2 a 443-as TCP porton (fallback)
listen 443 ssl;
ssl_certificate /etc/ssl/certs/example.crt;
ssl_certificate_key /etc/ssl/private/example.key;
# Alt-Svc fejléc: jelezzük a böngészőnek, hogy HTTP/3 elérhető
add_header Alt-Svc 'h3=":443"; ma=86400';
# QUIC-specifikus beállítások
ssl_early_data on; # 0-RTT engedélyezése
location / {
proxy_pass http://backend;
}
}
103 Early Hints: a szerver „előzetes figyelmeztetése"
A HTTP 103 Early Hints egy viszonylag új mechanizmus, amivel a szerver még a tényleges válasz előtt tippeket küldhet a böngészőnek arról, milyen erőforrásokra lesz szüksége. A böngésző így már a szerver feldolgozási ideje alatt elkezdhet DNS-feloldást, TCP-kapcsolódást vagy akár erőforrás-letöltést.
Hogyan működik?
A hagyományos folyamat egyszerű (és lassú):
- Böngésző kérést küld → Szerver dolgozik (200-500 ms) → Válasz megérkezik → Böngésző elemzi a HTML-t → Felfedezi a szükséges CSS/JS/font fájlokat → Elkezdi letölteni őket.
Early Hints-szel viszont:
- Böngésző kérést küld → Szerver azonnal küld egy 103-as választ a kritikus erőforrásokkal → Böngésző elkezdi a letöltéseket → Szerver közben dolgozik → Végleges 200-as válasz megérkezik → A böngésző már előrébb tart.
HTTP/1.1 103 Early Hints
Link: </styles/critical.css>; rel=preload; as=style
Link: </fonts/inter-var.woff2>; rel=preload; as=font; crossorigin
Link: <https://cdn.example.com>; rel=preconnect
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
<!DOCTYPE html>
...
Gyakorlati tapasztalatok és korlátok
A Shopify nagyszabású tesztelése szerint az Early Hints asztali eszközökön mérsékelt, de mérhető javulást hozott, különösen 1-3 előtöltött erőforrás esetén. Van viszont egy fontos figyelmeztetés: mobilon az Early Hints bizonyos esetekben lassíthatja a teljesítményt. Ennek oka, hogy a mobil eszközök korlátozott sávszélessége és CPU-ja nem mindig bírja el a párhuzamos letöltések extra terhelését.
Ajánlott gyakorlatok:
- Csak a legkritikusabb erőforrásokat jelezzük Early Hints-ként (LCP-hez kapcsolódó képek, kritikus CSS, fontos betűtípusok).
- Maximum 2-3 erőforrást adjunk meg — a túl sok hint kontraproduktív.
- Teszteljünk valós felhasználói adatokkal (CrUX), ne csak szintetikus benchmarkokkal.
- A böngészőtámogatás szerencsére jó: a Chromium és a Firefox támogatja a preload és preconnect hinteket, a Safari egyelőre csak a preconnect-et.
Resource Hints: a böngésző proaktív segítése
Az Early Hints mellett a HTML-ben elhelyezett resource hintek is sokat számíthatnak az érzékelt betöltési idő csökkentésében:
<!-- DNS előfeloldás: ~20-120 ms megtakarítás -->
<link rel="dns-prefetch" href="https://cdn.example.com">
<!-- Kapcsolat előkészítése: DNS + TCP + TLS = ~100-300 ms megtakarítás -->
<link rel="preconnect" href="https://cdn.example.com">
<!-- Kritikus erőforrás előtöltése: a böngésző azonnal elkezdi letölteni -->
<link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/images/hero.avif" as="image" fetchpriority="high">
<!-- Következő oldal előkészítése navigációhoz -->
<link rel="prefetch" href="/next-page.html">
A fetchpriority="high" attribútum különösen hasznos az LCP-elemek számára: jelzi a böngészőnek, hogy ezt az erőforrást a többi előtt kell letöltenie. A 2025-ös CrUX adatok szerint az LCP négy alkomponensre bontható (TTFB, Resource Load Delay, Resource Load Time, Element Render Delay), és a resource hintek elsősorban a Resource Load Delay csökkentésében segítenek.
Service Worker gyorsítótárazás: az alkalmazásszintű kontroll
A Service Worker egy programozható proxy a böngészőben, ami teljes kontrollt ad a hálózati kérések felett. Míg a HTTP Cache-Control fejlécek és a CDN-ek a szerver oldalról szabályozzák a gyorsítótárazást, a Service Worker a kliens oldalon teszi ugyanezt — és bizonyos esetekben még hatékonyabban.
A legfontosabb Service Worker gyorsítótárazási stratégiák
1. Cache First (Gyorsítótár először): Mindig a helyi gyorsítótárból szolgáljuk ki, és csak akkor fordulunk a hálózathoz, ha nincs találat. Ideális statikus eszközökhöz (CSS, JS, képek, betűtípusok).
// Service Worker: Cache First stratégia
self.addEventListener('fetch', (event) => {
// Csak statikus eszközökre alkalmazzuk
if (event.request.url.match(/\.(css|js|woff2|png|jpg|avif|webp)$/)) {
event.respondWith(
caches.match(event.request).then((cachedResponse) => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(event.request).then((networkResponse) => {
// Mentés a gyorsítótárba későbbi használatra
const cache = caches.open('static-v1');
cache.then(c => c.put(event.request, networkResponse.clone()));
return networkResponse;
});
})
);
}
});
2. Stale-While-Revalidate (Elavult, miközben frissítünk): A leggyakrabban ajánlott stratégia, és nem véletlenül. Azonnal kiszolgálja a gyorsítótárazott verziót, miközben a háttérben frissíti. Kiváló egyensúly a sebesség és a frissesség között.
// Service Worker: Stale-While-Revalidate stratégia
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('/api/articles')) {
event.respondWith(
caches.open('api-cache').then(async (cache) => {
const cachedResponse = await cache.match(event.request);
// Háttérfrissítés indítása (nem várjuk meg)
const fetchPromise = fetch(event.request).then((networkResponse) => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
// Ha van gyorsítótárazott verzió, azt adjuk vissza azonnal
// Egyébként várjuk meg a hálózati választ
return cachedResponse || fetchPromise;
})
);
}
});
3. Network First (Hálózat először): Először a hálózatról próbáljuk, és csak hiba esetén nyúlunk a gyorsítótárhoz. API-válaszoknál és dinamikus tartalmaknál hasznos, ahol a frissesség fontosabb a sebességnél.
A Workbox könyvtár
A Google Workbox könyvtára jelentősen egyszerűsíti a Service Worker gyorsítótárazás implementálását. Ha nem akarsz mindent kézzel írni (és nem kellene), ez a legjobb kiindulópont:
// workbox-config.js — Workbox alapú gyorsítótárazás
import { registerRoute } from 'workbox-routing';
import { CacheFirst, StaleWhileRevalidate, NetworkFirst } from 'workbox-strategies';
import { ExpirationPlugin } from 'workbox-expiration';
// Statikus eszközök: Cache First, max 60 bejegyzés, 30 nap
registerRoute(
({ request }) => request.destination === 'style' ||
request.destination === 'script' ||
request.destination === 'font',
new CacheFirst({
cacheName: 'static-resources',
plugins: [
new ExpirationPlugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60 }),
],
})
);
// Képek: Cache First, max 100 bejegyzés, 7 nap
registerRoute(
({ request }) => request.destination === 'image',
new CacheFirst({
cacheName: 'images',
plugins: [
new ExpirationPlugin({ maxEntries: 100, maxAgeSeconds: 7 * 24 * 60 * 60 }),
],
})
);
// API-hívások: Stale While Revalidate
registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new StaleWhileRevalidate({
cacheName: 'api-responses',
plugins: [
new ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 24 * 60 * 60 }),
],
})
);
// HTML oldalak: Network First (offline fallback)
registerRoute(
({ request }) => request.mode === 'navigate',
new NetworkFirst({
cacheName: 'pages',
plugins: [
new ExpirationPlugin({ maxEntries: 25, maxAgeSeconds: 7 * 24 * 60 * 60 }),
],
})
);
A teljes gyorsítótárazási hierarchia: mindent összefogva
A valóságban ezek a technikák nem egymás alternatívái, hanem egymásra épülő rétegek. Íme a teljes kép, ahogyan egy kérés áthalad a rendszeren:
- Service Worker cache (böngésző): A leggyorsabb — ha van találat, nulla hálózati késleltetéssel válaszolunk.
- Böngésző HTTP cache: A Cache-Control fejlécek alapján a böngésző helyi gyorsítótárából szolgálja ki.
- CDN edge cache: Ha a böngészőben nincs meg, a legközelebbi CDN edge szerver szolgálja ki.
- CDN regionális cache (origin shield): Ha az edge-en sincs meg, a regionális szinten próbálkozik.
- Origin szerver + alkalmazás-szintű cache (Redis/Memcached): Az origin szerver a saját gyorsítótárából szolgálja ki, ha lehetséges.
- Adatbázis: Végső megoldásként az adatbázisból kérdezzük le az adatot.
Minden réteg csökkenti az esélyt, hogy a kérés eljut a következő, lassabb szintig. A cél egyszerű: a kérések minél nagyobb hányadát a lehető leggyorsabb rétegben kiszolgálni.
Mérés és monitorozás: nem optimalizálhatunk, amit nem mérünk
A TTFB és a gyorsítótárazás hatékonyságának mérése elengedhetetlen. Mert hiába csinálunk bármit is, ha nem tudjuk pontosan, mennyit javított. Íme a legfontosabb eszközök:
Navigation Timing API
// TTFB mérése a Navigation Timing API-val
const [navigation] = performance.getEntriesByType('navigation');
const ttfb = navigation.responseStart - navigation.requestStart;
const dnsTime = navigation.domainLookupEnd - navigation.domainLookupStart;
const tcpTime = navigation.connectEnd - navigation.connectStart;
const tlsTime = navigation.requestStart - navigation.secureConnectionStart;
const serverTime = navigation.responseStart - navigation.requestStart;
console.log(`TTFB: ${ttfb.toFixed(0)} ms`);
console.log(` DNS: ${dnsTime.toFixed(0)} ms`);
console.log(` TCP: ${tcpTime.toFixed(0)} ms`);
console.log(` TLS: ${tlsTime.toFixed(0)} ms`);
console.log(` Szerver: ${serverTime.toFixed(0)} ms`);
// Küldés az analitikai rendszerbe
navigator.sendBeacon('/analytics', JSON.stringify({
metric: 'ttfb',
value: ttfb,
breakdown: { dns: dnsTime, tcp: tcpTime, tls: tlsTime, server: serverTime }
}));
CDN cache hatékonyság mérése
A legtöbb CDN (Cloudflare, Fastly, Akamai) részletes analitikát nyújt a cache találati arányról. A célszámok:
- Cache hit ratio > 90%: Statikus eszközöknél 95%+ a cél, dinamikus tartalmaknál 70-85% már kiváló.
- Alacsony origin load: Ha a CDN jól működik, az origin szerver terhelése minimális.
- Monitoring az x-cache fejléccel: A válasz fejlécében az
x-cache: HITvagycf-cache-status: HITjelzi, hogy a CDN-ből szolgáltuk ki a tartalmat.
Átirányítások minimalizálása: a rejtett TTFB-gyilkos
Az egyik leggyakrabban figyelmen kívül hagyott TTFB-tényező az átirányítások (redirects) láncolata. Minden egyes átirányítás egy teljes extra kérés-válasz ciklust jelent — DNS-feloldással, TCP-kapcsolódással és szerver válasszal együtt.
Tipikus bűnösök:
http://example.com→https://example.com→https://www.example.com(két átirányítás, +200-600 ms)https://example.com/oldpage→https://example.com/newpage→https://example.com/finalpage
Megoldások:
- HSTS (HTTP Strict Transport Security): A
Strict-Transport-Securityfejléc és a HSTS preload lista segítségével a böngésző automatikusan HTTPS-re vált, átirányítás nélkül. - Egyetlen kanonikus URL: Döntsünk, hogy www-vel vagy anélkül legyen a kanonikus domain, és minden más formát egy lépésben irányítsunk át ide.
- Belső linkek frissítése: A régi URL-ek helyett mindig a végleges URL-re linkeljünk a saját kódunkban.
# nginx: egyetlen átirányítás a kanonikus URL-re
server {
listen 80;
listen 443 ssl;
server_name example.com;
# HSTS fejléc: 1 évig érvényes, includeSubDomains + preload
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Minden kérést a www-s verzióra irányítunk, egy lépésben
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
location / {
proxy_pass http://backend;
}
}
Ellenőrzőlista: TTFB és gyorsítótárazás optimalizálás lépésről lépésre
Végül összefoglaljuk a legfontosabb lépéseket. Mentsd el ezt a listát — jól fog jönni:
- Mérjük a kiindulópontot: Használjuk a CrUX adatokat vagy a Navigation Timing API-t a jelenlegi TTFB meghatározásához.
- Optimalizáljuk a szerver válaszidőt: Adatbázis-indexek, lekérdezés-gyorsítótár (Redis), Streaming SSR, statikus generálás ahol lehetséges.
- Konfiguráljuk a CDN-t: Válasszunk CDN-t (Cloudflare, Fastly, Akamai), engedélyezzük a tiered caching-et, állítsuk be az origin shield-et.
- Állítsuk be a Cache-Control fejléceket: Különböző stratégia a statikus eszközöknek (immutable, hosszú max-age), HTML-nek (rövid max-age, stale-while-revalidate) és API-knak.
- Engedélyezzük a HTTP/3-at: Ha a CDN-ünk vagy szerverünk támogatja, konfiguráljuk a QUIC-ot és a 0-RTT-t.
- Implementáljuk az Early Hints-et: A legkritikusabb 2-3 erőforrásra korlátozzuk, és figyeljünk a mobil teljesítményre.
- Adjunk hozzá resource hinteket: preconnect, preload és dns-prefetch a kritikus erőforrásokhoz és harmadik fél domainekhez.
- Fontoljuk meg a Service Worker-t: Stale-while-revalidate stratégia az API-hívásokhoz, Cache First a statikus eszközökhöz.
- Monitorozzuk folyamatosan: CrUX adatok, CDN cache hit ratio, szintetikus tesztek (Lighthouse, WebPageTest) és valós felhasználói mérések (RUM).
Összefoglalás: a TTFB nem opcionális
A TTFB optimalizálása és a gyorsítótárazási stratégiák helyes alkalmazása nem puszta technikai feladat — ez az alapja minden egyéb teljesítményjavításnak. Hiába optimalizáljuk a CSS renderelést, a JavaScript bundleket vagy a képeket, ha az első bájt megérkezése már önmagában túl sokáig tart.
A jó hír az, hogy a legtöbb TTFB-javítás nem igényel alkalmazáskód-módosítást. A CDN beállítása, a Cache-Control fejlécek finomhangolása és a HTTP/3 engedélyezése infrastrukturális szintű változtatások, amelyek az egész webhelyre hatnak. Az edge computing és a Service Worker rétegek hozzáadása pedig tovább finomítja a teljesítményt azoknak a felhasználási eseteknek, ahol minden milliszekundum számít.
A Web Almanac adatai azt mutatják, hogy a webes teljesítmény fejlődése lassú, de folyamatos. A mobilos TTFB-értékek még mindig messze elmaradnak az asztaliaktól — az itt bemutatott technikák alkalmazásával éppen ez a szakadék szűkíthető. Merjünk a „jó" TTFB 800 ms-os küszöbe alá célozni: a 200-400 ms-os tartomány az, ahol a felhasználók valóban érezni fogják a különbséget.
Fontos megjegyezni, hogy a TTFB-optimalizálás nem egyszeri feladat. Az infrastruktúra változásai, az új funkciók bevezetése, a harmadik fél szkriptek hozzáadása — mind hatással lehetnek a szerver válaszidőre. Állítsunk be automatizált monitorozást és riasztásokat: ha a 75. percentilis TTFB egy meghatározott küszöb fölé emelkedik, azonnal kapjunk értesítést. A proaktív megközelítés sokkal hatékonyabb, mint a reaktív hibakeresés (és sokkal kevésbé stresszes).
Érdemes azt is szem előtt tartani, hogy a különböző felhasználói szegmensek eltérő TTFB-élményt kaphatnak. Egy európai felhasználó CDN-ről kapott válasza és egy ázsiai felhasználó origin-ről kapott válasza között akár többszörös különbség is lehet. A CrUX adatok országonkénti bontása segíthet felfedezni ezeket az eltéréseket és célzott optimalizálásokat végrehajtani.