9.5 Frontend performance alapok
Áttekintő
A frontend performance egy furcsa területe a fejlesztői munkának: mindenki érzi, ha lassú egy oldal, de kevesen tudják megmondani, miért lassú – és még kevesebben tudják megmondani, mit kellene előbb javítani.
Ez az alfejezet nem mér milliszekundumokat, és nem leszel Google-szintű performance mérnök utána. De megtanulod felismerni a leggyakoribb problémákat, és tudni fogod, hol érdemes elkezdeni a diagnosztikát.
A junior fejlesztők legtipikusabb hibája: nem mérik, csak találgatnak. Megnéznek egy oldalt, azt mondják „lassú a képek miatt", és elkezdenek képeket optimalizálni – miközben a valódi probléma egy blokkoló JavaScript fájl. Ebben az alfejezetben pontosan ezt a gondolkodásmódot fogjuk megszüntetni.
Részletes leírás
Miért lassú egy weboldal? – A nagy kép
Mielőtt bármi konkrétat tanulnánk, értsd meg, hogy a böngésző mit csinál, amikor megnyitja az oldaladat:
- DNS feloldás (domain → IP cím)
- TCP kapcsolat felépítése
- HTTP(S) handshake
- HTML letöltése
- HTML parse-olása – és itt kezdődnek a problémák
- CSS letöltése és parse-olása
- JavaScript letöltése és futtatása
- Képek letöltése
- Az oldal megjelenítése (render)
Minden egyes lépés lelassíthat mindent, ami utána jön. A probléma nem mindig ott van, ahol keresed.
Képméret és formátum hatása
A képek a legtöbb weboldal legnagyobb erőforrásai. Egy meg nem optimalizált kép könnyedén 3-5 MB lehet, ami mobilon, gyenge WiFi-n komoly lassúságot okoz.
Méretek:
- A böngészőben 400×300 pixelként megjelenített kép mögött ne legyen 2000×1500-as eredeti
- Ha a kép 400×300-ban jelenik meg, 400×300-as (vagy max 800×600 @2x Retina) fájl elég
Formátumok (2026-ban):
- JPEG – fotókhoz, veszteséges, jó tömörítés
- PNG – áttetsző képekhez, veszteségmentes, nagyobb fájlméret
- WebP – modern, kisebb méret, mint JPEG/PNG, szinte minden böngésző támogatja
- AVIF – még jobb tömörítés mint WebP, de nem minden helyen támogatott
- SVG – ikonokhoz, logókhoz; vektoros, tetszőlegesen skálázható, szöveges fájl
Egy egyszerű fejléc fotónál a WebP formátum önmagában 40-60%-os méretcsökkentést hozhat JPEG-hez képest.
A hibás gondolkodás: „majd a szerver optimalizálja" vagy „úgyis gyors az internet". Seniorként te sem gondolsz rá, junior fejlesztőként viszont már most érdemes tudni, hogy ez a te felelősséged is – nem csak a designeré.
Renderblocking erőforrások
Ez az egyik legfontosabb, és legkevésbé ismert fogalom.
Amikor a böngésző parse-olja a HTML-t és belefut egy <script> vagy <link rel="stylesheet"> tagbe, leáll – megvárja, hogy az erőforrás letöltődjön és feldolgozódjon, mielőtt folytatná. Ezt hívjuk render-blockingnak.
CSS render-blocking:
<!-- Ez leállítja az oldal parse-olását, amíg a CSS le nem tölt -->
<link rel="stylesheet" href="/styles.css">
A CSS blokkolja a renderelést, mert a böngészőnek tudnia kell, hogy a stílusok nélkül nem mutathat helyes oldalt. Ez általában elfogadható – de ha óriási CSS fájlod van, az lassít.
JavaScript render-blocking (a komolyabb probléma):
<!-- Ez leállítja az oldal parse-olását -->
<script src="/app.js"></script>
<!-- Ez NEM blokkoló – aszinkron letöltés -->
<script src="/app.js" async></script>
<!-- Ez NEM blokkoló, de a HTML parse után fut le (legtöbbször ezt akarod) -->
<script src="/app.js" defer></script>
Ha a <script> taged a <head>-ben van defer nélkül, az egész oldal megvárja, amíg a JavaScript letölt és lefut – a felhasználó addig üres képernyőt lát.
Ökölszabály: Minden saját JavaScript fájlodnál használj defer-t. Kivétel: ha a scriptnek feltétlenül a HTML parse előtt kell futnia (analytics, A/B tesztek – de ezekre te junior fejlesztőként nem fogsz rájönni azonnal).
Lazy loading képeknél
Az oldal betöltésekor a böngésző alapértelmezetten minden képet letölt – még azokat is, amelyek a görgetési vonalon kívül vannak és a felhasználó talán soha nem is látja őket.
A lazy loading megoldja ezt:
<!-- A kép csak akkor töltődik le, amikor közel ér a viewport-hoz -->
<img src="/termek-foto.webp" alt="Termék fotó" loading="lazy">
A loading="lazy" attribútum natívan támogatott minden modern böngészőben. Egy sorral bevezethető, és egy képintenzív oldalon (pl. terméklista, portfólió) drámai különbséget hozhat az első betöltési időben.
Fontos: A „hajtás feletti" (above the fold) képekre, amelyek az oldal első betöltésekor láthatók, ne tegyél lazy loading-ot – ott épp az ellenkezője igaz: minél hamarabb töltődjön le.
Bundle méret és kód-splitting
Ha modern JavaScript frameworköt (React, Vue, Angular) használsz, a build folyamat összecsomagolja az összes JavaScript kódot egy vagy több „bundle" fájlba.
A probléma: Az egyetlen hatalmas bundle-fájl azt jelenti, hogy a belépési oldal megnyitásakor a böngésző az összes JavaScript-et letölti és feldolgozza – még azokat az oldalakat is, amelyeket a felhasználó esetleg soha nem látogat meg.
Mi az a kód-splitting? Az alkalmazás JavaScript kódját több kisebb csomagra (chunk) osztjuk, amelyeket a böngésző csak akkor tölt le, amikor szükség van rájuk.
// Dinamikus import – csak akkor töltődik le a CheckoutPage,
// amikor a felhasználó a fizetési oldalra navigál
const CheckoutPage = React.lazy(() => import('./CheckoutPage'));
Az eredmény: az első oldalbetöltés sokkal gyorsabb, mert kevesebb kódot kell feldolgozni.
Juniorként mit kell ebből tudnod?
- Tudj arról, hogy a bundle mérete számít
- Ismerd fel, ha egy projekten nincs kód-splitting (az összes JS egy fájlban van)
- Ha a bundle analyzer eszközt futtatod (
webpack-bundle-analyzervagy hasonló), látni fogod, melyik csomag mekkora részt foglal el
A konkrét implementáció frameworktől függ, és általában a senior fejlesztők állítják be – de tudnod kell, hogy miért van rá szükség.
Mikor rontja a performance-t a túl sok JavaScript?
A JavaScript különleges erőforrás: letölteni, parse-olni, kompilálni és futtatni is kell – ez mind időbe telik. 1 MB JavaScript sokkal lassabb mint 1 MB kép, mert a kép csak letöltés és megjelenítés, a JavaScript mindhárom plusz a futtatás.
A három főbb probléma:
1. Letöltési méret Nagy bundle = sok letöltési idő. Különösen mobilon, lassabb hálózaton.
2. Parse és kompilálás A böngésző V8 motorja minden egyes JS fájlt parse-ol és kompilál. Ez CPU-intenzív művelet – olcsó laptopon vagy régi mobilon ez érzékelhetően lassú lehet.
3. Main thread blokkolás A JavaScript egyetlen szálon (main thread) fut. Ha egy script sokáig fut (pl. nagy adatfeldolgozás), az egész felhasználói felület lefagy – görgetés, kattintás, minden.
Mikor jelzőlámpa ez junior fejlesztőnek?
- Ha egy egyszerű landing page 2+ MB JavaScript-et tölt be
- Ha az oldal hosszú ideig nem reagál a kattintásokra (Long Tasks a DevTools-ban)
- Ha egy
npm installután a bundle mérete hirtelen megnőtt egy csomag hozzáadásával
A diagnosztika eszközei
A legtöbb diagnosztika a böngésző beépített DevTools-ában elvégezhető. Két fontosabb panel:
Network tab:
- Látod az összes letöltött erőforrást, azok méretét és betöltési idejét
- Szűrhetsz JS, CSS, képek szerint
- Látod, melyik erőforrás blokkoló és melyik nem
Lighthouse (Chrome DevTools):
- Automatikus teljesítmény-audit
- Pontszámot ad és konkrét javaslatokat tesz
- Mutatja a „Largest Contentful Paint", „Total Blocking Time" és hasonló metrikákat
Amit keresni érdemes:
- Nagyon nagy fájlok (JS > 500 KB, képek > 200 KB)
- Render-blocking erőforrások
- Képek, amelyek nincsenek lazy loading-gal betöltve
- Sok HTTP request (bár ez HTTP/2-vel kevésbé kritikus)
Életszerű példák
Eset 1: A portfólió oldal, ami mindenkit elriaszt
Péter portfólió oldalát megnézed a telefononon, és 8 másodpercig fehér képernyő van. Mi lehet a baj?
DevTools Network tab-ban látod:
app.js– 2.3 MB (a<head>-ben,defernélkül)hero-background.jpg– 4.1 MB (eredeti fényképész fájl)- 12 portfólió projekt képe – összesen 15 MB
A valódi probléma mindhárom: a blokkoló JS, az óriási kép, és a lazy loading hiánya.
Fix:
defera script taghez – azonnali javuláshero-background.jpgkonvertálás WebP-re, átméretezés 1920px szélesre – 4.1 MB → kb. 180 KBloading="lazy"a portfólió képekre
Eredmény: 8 másodpercről kb. 1.5 másodpercre csökken az első megjelenés.
Eset 2: A React alkalmazás, ami lassabb mint kellene
Mária első React alkalmazásában minden oldal lassabbnak tűnik, mint egy normál weboldal. A bundle fájl mérete 3.8 MB.
Megnyitod a bundle analyzer-t, és látod:
moment.js– 520 KB (egy dátum formázó könyvtár, csak egy helyen használják)lodash– 70 KB (az egészet importálják, de csak 3 függvényt használnak)- Nincs kód-splitting – az összes oldal kódja egy fájlban
Fix:
moment.jscserélésedate-fns-re (tree-shakeable, az összes dátumfüggvény helyett csak azok importálódnak, amiket valóban használsz)lodashhelyett natív JavaScript metódusok, vagy tree-shakeable import- React.lazy() bevezetése a nagyobb oldalakhoz
Ez nem junior feladat egyedül megoldani – de felismerni igen.
Eset 3: A terméklista, ami görgetésnél fagy
Kata webshopján a terméklistán 200 kép jelenik meg. Görgetés közben a böngésző akadozik.
Mi történik: az oldal betöltésekor 200 képet próbál egyszerre letölteni és megjeleníteni. Ez meghaladja a böngésző HTTP párhuzamos kérés limitjét, és felesleges CPU+memória használatot okoz.
Fix:
<img src="/termek-001.webp" alt="Termék neve" loading="lazy">
Egy attribútum, és a probléma megszűnik.
Példafeladat
Szimulált diagnosztika feladat
Képzeld el, hogy az alábbi helyzetet kapod a csapatban: a cég marketingoldala lassan tölt be, a vezető azt mondta, „csináljatok vele valamit". Te kapsz hozzáférést a DevTools-hoz.
A Network tab az alábbiakat mutatja:
Erőforrás Méret Típus Blokkoló?
index.html 12 KB HTML
main.css 180 KB CSS igen
analytics.js 42 KB JS igen (head, no defer)
app.bundle.js 1.8 MB JS igen (head, no defer)
hero-image.jpg 3.2 MB Kép
team-photo-1.jpg 1.1 MB Kép
team-photo-2.jpg 980 KB Kép
team-photo-3.jpg 1.3 MB Kép
icons.png 220 KB Kép
A Lighthouse audit ezen felül megjegyzi:
- „Serve images in next-gen formats"
- „Defer offscreen images"
- „Eliminate render-blocking resources"
- „Reduce unused JavaScript"
Feladatok:
- Sorolj fel legalább 4 konkrét problémát, amelyeket a fentiek alapján azonosítasz!
- Rendezd prioritás szerint: melyik változtatás hozná a legnagyobb javulást a legkisebb befektetéssel?
- Melyik változtatás megvalósítható egyedül, frontend fejlesztőként, és melyikhez kell más csapattag (designer, backend, DevOps)?
- Mit javasolnál az
app.bundle.jsméretének csökkentésére? (Nem kell technikai megvalósítás, csak az elvek.)
Mintamegoldás:
1. Azonosított problémák:
analytics.jsésapp.bundle.jsrender-blocking (nincs defer) → az oldalon lévő tartalom csak ezek után jelenik megapp.bundle.js1.8 MB – valószínűleg nincs kód-splittinghero-image.jpg3.2 MB – nem optimalizált, valószínűleg nincs WebP verzió- Team fotók összesen ~3.4 MB – nem szükséges mindet azonnal letölteni
icons.png220 KB – gyanúsan nagy, valószínűleg SVG-re kellene cserélni
2. Prioritás (könnyű → nehéz, hatás szerint):
deferhozzáadása a script tagekhez – 5 perc, azonnali javulásloading="lazy"a team fotókra – 5 perc, azonnali javulás- Képek konvertálása WebP-re + átméretezés – néhány óra, nagy javulás
- Bundle size csökkentése (kód-splitting, tree-shaking) – nagyobb munka
3. Ki tud mit megvalósítani:
- A HTML módosítások (defer, lazy loading) – egyedül, frontend fejlesztőként
- Képoptimalizálás – designerrel együtt (ők adják az eredeti fájlokat)
- Bundle méret csökkentése – senior fejlesztő bevonásával
4. Bundle méret csökkentése:
- Kód-splitting bevezetése (React.lazy / dynamic import) – az oldalak kódja csak akkor töltődjön le, amikor szükség van rájuk
- Felesleges vagy túl nagy npm csomagok azonosítása (bundle analyzer eszközzel)
- Tree-shaking – csak a ténylegesen használt funkciók kerüljenek a bundle-be
Tesztfeladatok
1. feladat
Melyik HTML attribútum akadályozza meg, hogy egy kép azonnal letöltődjön a böngészőben?
a) loading="async"
b) loading="lazy"
c) defer
d) async
2. feladat
Egy <script src="app.js"> tag a <head> szekcióban, defer vagy async nélkül:
a) Nem befolyásolja az oldal betöltési sebességét
b) Csak a képek letöltése után fut le
c) Megakadályozza, hogy a böngésző folytassa a HTML parse-olást, amíg a script letölt és lefut
d) Automatikusan aszinkronná válik HTTP/2 esetén
3. feladat
Párosítsd a problémát a megfelelő megoldással!
| Probléma | Megoldás |
|---|---|
| A) Nagy JPEG fájlok a termékoldalon | 1. loading="lazy" |
| B) Script blokkolja az oldal megjelenítését | 2. WebP konverzió |
| C) Az alkalmazás összes kódja egyszerre töltődik le | 3. defer attribútum |
| D) Görgetés közben sok kép töltődik le egyszerre | 4. Kód-splitting |
4. feladat
Melyik állítás igaz a JavaScript bundle méretéről?
a) Csak a letöltési méret számít – ha az gyors, minden rendben van
b) A JavaScript feldolgozása (parse, kompilálás, futtatás) is lassítja az oldalt, nem csak a letöltés
c) Modern böngészőkben a JavaScript feldolgozása azonnali, csak régi böngészőkben lassú
d) A bundle mérete csak server-side renderingnél számít
5. feladat
Melyik képformátum a legmegfelelőbb egy vektoros ikonhoz?
a) JPEG
b) PNG
c) SVG
d) WebP
6. feladat
Egy weboldalon 50 termékképet kell megjeleníteni egy listában. A felhasználó az oldal tetején landol, ahol az első 6 kép látható. Melyik megközelítés a helyes?
a) Minden képre loading="lazy" – egyszerű és egységes
b) Az első 6 képre normál betöltés, a többire loading="lazy"
c) Minden képet egyszerre betölteni – a böngésző majd kezeli
d) Semmit nem kell tenni, a modern böngészők automatikusan lazy loadelnek
7. feladat
Mi az a defer attribútum hatása JavaScript fájloknál?
a) A script aszinkron módon töltődik le, és azonnal lefut, amint kész
b) A script nem töltődik le, csak akkor, ha a felhasználó kattint
c) A script aszinkron módon töltődik le, de csak a HTML parse befejezése után fut le
d) A script teljesen kimarad az oldalból
8. feladat
Melyik DevTools panel a legalkalmasabb annak ellenőrzésére, hogy melyik erőforrások lassítják az oldal betöltését?
a) Console
b) Elements
c) Network
d) Sources
9. feladat
Egy React alkalmazásban moment.js könyvtárat használnak dátumok formázásához. A bundle analyzer azt mutatja, hogy a moment.js 520 KB. Mi az optimális megközelítés?
a) Hagyni ahogy van – ha működik, ne nyúlj hozzá
b) Cserélni egy kisebb, tree-shakeable alternatívára (pl. date-fns)
c) A moment.js-t CDN-ről betölteni a bundle-ből kivéve
d) Minify-olni a moment.js-t kézzel
10. feladat
Miért lassabb 1 MB JavaScript, mint 1 MB képfájl?
a) Nem lassabb – mindkettő ugyanannyi idő alatt dolgozódik fel
b) Mert a JavaScript titkosítva van és vissza kell fejteni
c) Mert a JavaScript-et le kell tölteni, parse-olni, kompilálni és futtatni is – a kép csak letöltés és megjelenítés
d) Mert a JavaScript mindig a main thread-en tölt be, a kép nem
Megoldások
- b –
loading="lazy"
- c – Megakadályozza az oldal parse-olásának folytatását
- Párosítás: A→2, B→3, C→4, D→1
- b – A feldolgozás (parse, kompilálás, futtatás) is lassít
- c – SVG (vektoros, skálázható, kis méretű szöveges fájl)
- b – Az első, azonnal látható képekre normál betöltés, a többire lazy loading
- c – Aszinkron letöltés, HTML parse utáni futtatás
- c – Network tab
- b – Kisebb, tree-shakeable alternatíva
- c – Letöltés + parse + kompilálás + futtatás (szemben a kép letöltés + renderelés párossal)