9.5 Frontend performance

← 9. Optimalizációs alapok

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:

  1. DNS feloldás (domain → IP cím)
  2. TCP kapcsolat felépítése
  3. HTTP(S) handshake
  4. HTML letöltése
  5. HTML parse-olása – és itt kezdődnek a problémák
  6. CSS letöltése és parse-olása
  7. JavaScript letöltése és futtatása
  8. Képek letöltése
  9. 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-analyzer vagy 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 install utá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, defer né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:

  1. defer a script taghez – azonnali javulás
  2. hero-background.jpg konvertálás WebP-re, átméretezés 1920px szélesre – 4.1 MB → kb. 180 KB
  3. loading="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:

  1. moment.js cserélése date-fns-re (tree-shakeable, az összes dátumfüggvény helyett csak azok importálódnak, amiket valóban használsz)
  2. lodash helyett natív JavaScript metódusok, vagy tree-shakeable import
  3. 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:

  1. Sorolj fel legalább 4 konkrét problémát, amelyeket a fentiek alapján azonosítasz!
  1. Rendezd prioritás szerint: melyik változtatás hozná a legnagyobb javulást a legkisebb befektetéssel?
  1. Melyik változtatás megvalósítható egyedül, frontend fejlesztőként, és melyikhez kell más csapattag (designer, backend, DevOps)?
  1. Mit javasolnál az app.bundle.js mé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 és app.bundle.js render-blocking (nincs defer) → az oldalon lévő tartalom csak ezek után jelenik meg
  • app.bundle.js 1.8 MB – valószínűleg nincs kód-splitting
  • hero-image.jpg 3.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.png 220 KB – gyanúsan nagy, valószínűleg SVG-re kellene cserélni

2. Prioritás (könnyű → nehéz, hatás szerint):

  1. defer hozzáadása a script tagekhez – 5 perc, azonnali javulás
  2. loading="lazy" a team fotókra – 5 perc, azonnali javulás
  3. Képek konvertálása WebP-re + átméretezés – néhány óra, nagy javulás
  4. 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émaMegoldás
A) Nagy JPEG fájlok a termékoldalon1. loading="lazy"
B) Script blokkolja az oldal megjelenítését2. WebP konverzió
C) Az alkalmazás összes kódja egyszerre töltődik le3. defer attribútum
D) Görgetés közben sok kép töltődik le egyszerre4. 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

  1. bloading="lazy"
  1. c – Megakadályozza az oldal parse-olásának folytatását
  1. Párosítás: A→2, B→3, C→4, D→1
  1. b – A feldolgozás (parse, kompilálás, futtatás) is lassít
  1. c – SVG (vektoros, skálázható, kis méretű szöveges fájl)
  1. b – Az első, azonnal látható képekre normál betöltés, a többire lazy loading
  1. c – Aszinkron letöltés, HTML parse utáni futtatás
  1. c – Network tab
  1. b – Kisebb, tree-shakeable alternatíva
  1. c – Letöltés + parse + kompilálás + futtatás (szemben a kép letöltés + renderelés párossal)
Scroll to Top