15. modulTeljesítmény: hydration, payload, bundle
Nuxt for Devs · 15. modul

Teljesítmény: hydration, payload, bundle

Három különböző dolgot szoktak „lassúságnak” hívni, és három különböző eszközzel kell javítani őket. Ez a modul szétválasztja a hármat, megmutatja a Nuxt késleltetett hidratálását — a legkonkrétabb kliensoldali nyereséget —, majd a Workers-specifikus részt: a bundle-limitet, a hidegindítást és a CPU-időt, valós számokkal és a méréshez tartozó parancsokkal.

15.1A három front

① HÁLÓZAT mennyi bájt megy át · JS/CSS bundle · HTML + payload · képek, fontok érinti: LCP mobilhálózaton ez a fő tétel ② KLIENS-CPU mennyit dolgozik a böngésző · JS parse + execute · hydration · reaktivitás, újrarenderelés érinti: INP olcsó gépen ez a fő tétel ③ SZERVER-CPU mennyit dolgozik a Worker · SSR renderelés · szerializálás, JSON · hidegindítás érinti: TTFB + SZÁMLA Workers-en ez pénzben mérhető
Ugyanaz a tünet („lassú”) mindhárom oszlopból jöhet. Először azonosítsd, melyik — enélkül a javítás vaktában lövés.

15.2Hydration — és a késleltetett hidratálás

A 2. modulból: minden komponens lefut a szerveren, majd újra a kliensen. A hydration az a fázis, amikor a böngésző „ráköti” a JS-t a már megjelenített HTML-re. Nagy oldalon ez a legdrágább kliensoldali tétel — és a felhasználó ezt úgy éli meg, hogy látszik az oldal, de nem reagál.

A Nuxt erre két, egymásra épülő eszközt ad:

Lazy prefix — a kód később töltődik

<template>
  <!-- csak akkor tölti le a komponens kódját, amikor tényleg kell -->
  <LazyExportDialog v-if="dialogNyitva" />
</template>
Önmagában ez nem elég. A Lazy a chunk-méretet szabályozza, nem a futásidőt: ha a komponens mégis renderelődik, ugyanúgy betöltődik és hidratálódik. A dokumentáció is figyelmeztet erre. A valódi nyereséghez a hidratálás idejét kell szabályozni — ez a következő.

Hidratálási stratégiák — ez a lényeg

<template>
  <!-- a hajtás alatti tartalom: csak amikor a nézetbe kerül -->
  <LazyActivityFeed hydrate-on-visible />

  <!-- másodlagos widget: amikor a böngésző ráér -->
  <LazyUsageChart hydrate-on-idle />

  <!-- nehéz szerkesztő: csak ha a felhasználó odamegy -->
  <LazyRichTextEditor hydrate-on-interaction="mouseover" />

  <!-- mobilon nem is kell -->
  <LazySidePanel hydrate-on-media-query="(min-width: 1024px)" />

  <!-- feltételhez kötve -->
  <LazyAdminTools :hydrate-when="isAdmin" />

  <!-- statikus tartalom: SOSEM hidratálódik — csak HTML marad -->
  <LazyMarketingFooter hydrate-never />
</template>
A hydrate-never a legalulértékeltebb. Rengeteg olyan komponens van egy oldalon, ami sosem lesz interaktív: lábléc, statikus fejléc, tartalmi blokk, jogi szöveg. Ezek SSR-ből megjelennek, aztán fölöslegesen hidratálódnak. A hydrate-never-rel kimaradnak a kliensoldali munkából — a HTML ugyanúgy ott van, csak nem fizetsz érte CPU-t. Ez a legolcsóbb teljesítmény-nyereség, amit egy meglévő oldalon elérhetsz.

A stratégiák egymást kizárják (egy komponensre egy), és a komponens @hydrated eseményt bocsát ki, amikor aktiválódott — hasznos, ha mérni akarod.

A harmadik eszköz: kevesebb interaktív komponens

15.3Payload

Az 5. modulból tudjuk, mi ez: a szerveroldali lekérések eredménye a HTML-be ágyazva. Két szempontból számít — méret (hálózat) és tartalom (szivárgás). A méretet így nézd meg:

curl -s https://app.pelda.hu/dashboard | wc -c
curl -s https://app.pelda.hu/dashboard | grep -o '__NUXT_DATA__.*' | wc -c
Ha a payload nagyMit tegyél
Teljes adatbázis-sorok utaznakDTO a server route-ban (5. modul) — ez egyszerre méret- és biztonsági javítás
Több száz elemű lista az első képernyőnLapozás vagy virtualizálás; az első 20 elég
Személyre szabott blokkokserver: false — kliensre kerül, és a HTML cache-elhetővé válik (7. modul)
Ugyanaz az adat többszörKözös key — a Nuxt egyszer tárolja (5. modul)

15.4Bundle — a Workers-limit

Itt jön a rész, ami Node-szerveren nem létezik. A Workernek mérethatára van, és a Nuxt-appok szerverkódja nem kicsi:

LimitFreePaid
Worker-méret gzip után3 MB10 MB
Worker-méret tömörítés előtt64 MB64 MB
Indulási idő (globális scope kiértékelése)1 másodperc1 másodperc
CPU-idő kérésenként10 ms30 s alapból, 5 percig állítható
Memória128 MB128 MB
Statikus fájlok száma (verziónként)20 000100 000
Fontos: a limit a Worker-kódra vonatkozik, nem a statikus assetekre. A .output/public/ tartalma külön megy (static assets), és arra más — sokkal nagyobb — korlátok élnek. Vagyis a kliensoldali JS-bundle mérete nem számít bele a 10 MB-ba; a .output/server/ viszont igen. Ez fontos, mert a két méretet külön kell figyelni és külön eszközzel javítani.

Mérés

# ① gyors méret-ellenőrzés, deploy nélkül
npx wrangler deploy --outdir bundled/ --dry-run
# Total Upload: 4231.61 KiB / gzip: 1180.23 KiB

# ② méret ÉS hidegindítási profil egyben (a 11.3-as CI-kapu)
npx wrangler check startup --config .output/server/wrangler.json \
  --outfile startup.cpuprofile

# ③ a KLIENS-bundle összetétele — mi hízott meg és miért
npx nuxi analyze

Mi fogyasztja el a Worker-bundle-t

TételNagyságrendMit tehetsz
ORM (TypeORM, Prisma)JelentősDrizzle/Kysely kisebb (11.3); ha marad, mérd
Node-polyfillek (nodejs_compat)KözepesCsak akkor kapcsold be, ha tényleg kell
i18n fordításokNyelvenként nőLusta betöltés nyelvenként, ne mindet a bundle-be
Nagy segédkönyvtárak (dátum, validáció, markdown)Változóawait import() a hívás helyén (11.5)
Barrel-fájlok (utils/index.ts)RejtettKilövik a tree-shakinget — ne csináld (3. modul)
Véletlenül becsomagolt séma vagy ORM a kliens felőlNagyimport type, ne érték-import (11.2)

Ha közelítesz a limithez

  1. Nézd meg, mi van benne. A --dry-run --outdir kimenete elemezhető: a legnagyobb modulok általában azonnal látszanak.
  2. Dinamikus import a ritka útvonalakra. A PDF-export, a CSV-generátor, az admin-eszközök nem kellenek minden kérésnél.
  3. Cseréld a nehéz függőséget. A legtöbb nagy csomagnak van kisebb alternatívája, vagy kiváltható egy platform-képességgel (kép → Cloudflare Images, 13. modul).
  4. Vágd szét több Workerre. Ha tényleg nem fér, a nehéz háttérmunka külön Workerbe kerülhet, és service bindinggel hívod. Ez egyben architekturális tisztulás is (9. modul „hagyd kint” listája).

15.5Hidegindítás

A Worker indulásakor lefut a globális scope: minden top-level import, minden modul-szintű kifejezés. Erre 1 másodperc a keret (2025 októberétől — korábban 400 ms volt). Ha ezt átléped, a deploy nem megy át.

// ✗ ez indulási időt fogyaszt, minden izolátum-indításnál
const nagyTablazat = buildLookupTable()          // modul-szinten fut le
const regexek = SZABALYOK.map(s => new RegExp(s))

// ✓ halaszd az első használatig
let _tabla: Lookup | null = null
function getTabla() { return _tabla ??= buildLookupTable() }
Egy szabály, két okból. A 6. modulban azt mondtuk: ne dolgozz modul-szinten, mert a megosztott állapot adatszivárgás. Most kiderül, hogy ugyanez a szabály teljesítmény-okból is igaz — a modul-szintű munka minden izolátum-indításnál újra lefut, és az indulási keretbe számít. Ha eddig nem volt elég indok, most van kettő.

A wrangler check startup által kiírt .cpuprofile megnyitható a Chrome DevTools „Performance” fülén — ott látod, melyik modul kiértékelése mennyi időt vitt el. Ha az indulás gyanúsan magas, ez az egyetlen eszköz, ami megmondja, miért.

15.6SSR CPU-idő — Workers-en ez számla

A kérésenkénti CPU-idő nem csak limit, hanem árazási tényező. Ami belefér:

Mi fogyaszt CPU-tMit tehetsz
A komponensfa rendereléseKevesebb komponens az első képernyőn; prerender ahol lehet (7. modul)
A payload szerializálásaKisebb DTO — ugyanaz a javítás, mint a 15.3-nál
SQL-építés kérésenkéntPrepared statements (11.2)
Jelszó-hashelésCsak bejelentkezéskor, rate limit mögött (10. modul)
Nagy JSON parse/stringifyStreamelj, ahol lehet (8. modul)
Kriptográfia (aláírás-ellenőrzés)Web Crypto natív — ne JS-implementációt használj
A legnagyobb CPU-megtakarítás nem optimalizálás, hanem elkerülés. Egy prerenderelt oldal nulla CPU-t fogyaszt (7. modul). Egy cache-találat nulla CPU-t fogyaszt. Egy ssr: false útvonal majdnem nullát. Mielőtt a renderelést gyorsítanád, kérdezd meg, kell-e egyáltalán rendereled — a legtöbb SaaS-ban az oldalak fele nem igényel kérésenkénti SSR-t.

15.7Core Web Vitals — reális célok

MetrikaCélMit befolyásol a Nuxt
LCP — a fő tartalom megjelenése< 2,5 sSokat: az SSR ezt javítja, a nagy bundle rontja. Képméret és font-betöltés is ide tartozik
INP — reagálás az interakcióra< 200 msSokat: a hydration és a fölösleges reaktivitás rontja. Itt segít a késleltetett hidratálás
CLS — elmozduló elrendezés< 0,1Közvetve: adj width/height-ot a képeknek, használj #fallback-et a <ClientOnly>-hoz, és @nuxt/fonts-ot a font-ugrás ellen
TTFB< 800 msSokat: SSR-idő + adatlekérés. Itt jön elő a 9. modul latency-paradoxona
A Lighthouse-pontszám nem a felhasználóid élménye. Egy laborban, gyors gépen mért 98 pont mellett is lehet rossz a valóság — más eszközök, más hálózat, más földrajz. A valós adathoz mezei mérés kell: a Cloudflare Web Analytics gyűjti a Core Web Vitalsokat valódi látogatóktól, cookie nélkül, és a Cloudflare-anyag 9. modulja tárgyalja. A Lighthouse-t használd regressziófigyelésre, a RUM-ot a valóság megismerésére.

15.8Teljesítmény-költségvetés

A számok akkor érnek valamit, ha a build elbukik, amikor átlépted őket. Kiindulási javaslat — igazítsd a saját appodhoz, de legyen:

MitKüszöbMiért ennyi
Worker-bundle (gzip)a limit 80%-aLegyen mozgástér, mielőtt a deploy bukna
Indulási profil800 ms (az 1 s 80%-a)Ugyanaz az elv
Kliens-JS az első oldalon~250 KB gzipEfölött mobilhálózaton érezhető
Payload egy oldalon~50 KBEfölött általában DTO-hiba van mögötte
Lighthouse (mobil, throttled)> 85Regressziófigyelésre, nem célnak
# CI-lépés: méret + indulás + titok-keresés egyben (12.3)
npm run build
node scripts/verify-bundle.mjs          # wrangler check startup + 80%-os guard
grep -ril "sk_live\|SESSION_PASSWORD" .output/public/ && exit 1
echo "OK"
Mi jön ezután? A 16. modul a tesztelésről és a hibakeresésről szól: @nuxt/test-utils és Vitest, mit érdemes tesztelni egy ilyen appon, a hydration mismatch szisztematikus felderítése, és a legnehezebb eset — a hiba, ami csak Workers-en jelentkezik.

15.9Ellenőrizd magad

  1. „Lassú az oldal.” Melyik három frontot kell szétválasztani, és mi tartozik hozzájuk?
    Válasz

    ① Hálózat — mennyi bájt megy át (bundle, HTML+payload, képek); főleg LCP-t érint. ② Kliens-CPU — parse, execute, hydration, reaktivitás; főleg INP-t érint. ③ Szerver-CPU — SSR, szerializálás, hidegindítás; TTFB-t érint, és Workers-en pénzben is mérhető. Amíg nem tudod, melyikről van szó, a javítás vaktában lövés.

  2. Mi a különbség a Lazy prefix és a hydrate-on-* stratégiák között?
    Válasz

    A Lazy a chunk-méretet szabályozza: a komponens kódja külön darabba kerül és később töltődik le. De ha a komponens renderelődik, ugyanúgy betöltődik és hidratálódik. A hydrate-on-* stratégiák a hidratálás idejét szabályozzák — láthatóságra, üresjáratra, interakcióra, media queryre, feltételre, vagy soha (hydrate-never).

  3. Melyik a legolcsóbb hydration-nyereség egy meglévő oldalon?
    Válasz

    A hydrate-never azokra a komponensekre, amik sosem lesznek interaktívak: lábléc, statikus fejléc, tartalmi blokkok, jogi szövegek. SSR-ből megjelennek, de kimaradnak a kliensoldali munkából — a HTML ugyanaz, csak nem fizetsz érte CPU-t.

  4. A kliens-JS-ed 4 MB. Belefér a Workers 10 MB-os limitbe?
    Válasz

    A kérdés félrevezető: a kliens-JS a .output/public/-ba kerül, ami static asset, és nem számít bele a Worker-méretbe. A 3/10 MB gzip-limit a .output/server/ Worker-kódra vonatkozik. A két méretet külön kell figyelni: az egyiket wrangler deploy --dry-run-nal, a másikat nuxi analyze-zal.

  5. Miért rossz modul-szinten munkát végezni — most már két okból?
    Válasz

    ① Biztonsági: a modul-scope megosztott a kérések között, tehát a kérés-hatókörű állapot ott szivárgást okoz (6. modul). ② Teljesítmény: a modul-szintű kód minden izolátum-indításkor lefut, és beleszámít az 1 másodperces indulási keretbe. Halaszd az első használatig (lusta inicializálás).

  6. Mi a legnagyobb CPU-megtakarítás egy SSR-es oldalon?
    Válasz

    Nem a renderelés gyorsítása, hanem az elkerülése: a prerenderelt oldal nulla CPU-t fogyaszt, a cache-találat nullát, az ssr: false útvonal majdnem nullát. Először azt kérdezd meg, kell-e kérésenként rendereled — a legtöbb SaaS-ban az oldalak fele nem igényli.

Előző14. modul — Layers és white-label Következő 16. modul — Tesztelés és hibakeresés