Az archívumból6 rész · 5 percÍrta: Dezső Mező · Megjelent .mdNext.jsPerformanceVercelWeb VitalsReact
Next.js 16 ban (2026 elején GA) sok új koncepció van, és az useState használat egy része ami működött 14 ben, 16 ban szétdől. Az utóbbi négy hónapban hat különböző Vercel projekt audit ját csináltuk meg, és mindenhol ott volt ugyanaz az 5 csapda. Ezek nem konfig dolgok, kódszintű hibák, és mind mérhető.
Mielőtt elkezdesz olvasni: a hivatalos node_modules/next/dist/docs/ t mindig nézd át, mert a Next.js 16 ban a 14 es API ról a 15 ön át a 16 ig sok minden megváltozott. A példák itt 16 specifikusak.
011. `use cache` és Suspense interakció · az LCP gyilkos
A use cache direktíva 16 ban hivatalos. A csapda: ha egy use cache jelölt komponensen belül Suspense boundary van, a cache nem terjed le, és a stream két külön részre szakad. Ez fizikailag jó (a felső rész gyors), de az LCP elem gyakran a Suspense boundary mögött van · az eredmény: cached oldal, nem cached LCP.
// Rossz · 16 ban LCP nő, a hero kép a Suspense ben van
async function Page() {
"use cache";
return (
<main>
<Header />
<Suspense fallback={<HeroSkeleton />}>
<Hero /> {/* LCP elem · a use cache nem fedi le */}
</Suspense>
</main>
);
}
// Jó · az LCP elemet kihúzzuk a Suspense ből, a hosszú lekérdezést tesszük be
async function Page() {
"use cache";
const heroData = await fetchHero();
return (
<main>
<Header />
<Hero data={heroData} />
<Suspense fallback={<RecsSkeleton />}>
<Recommendations />
</Suspense>
</main>
);
}Egy webshop projekten LCP 2.8s ről 1.2s re esett a refaktorral. INP nem változott.
022. 'use client' boundary szivárgás · a JS bundle duplázódik
A 14 ben már volt ez a csapda, 16 ban rosszabb, mert a partial prerendering miatt a határok cseppfolyósabbak. Tipikus hiba: egy 'use client' jelölt komponens importál egy server only modult (pl. egy db.ts t), ami megint importál szerver oldali utility ket. Ez a 16 ban nem dob fordítási hibát, hanem a szerver oldali kódot is bekapja a kliens bundle be.
// lib/db.ts · csak szerver, mert a `pg` import szerver only
import { Pool } from "pg";
export const pool = new Pool();
// components/cart-button.tsx · 'use client'
"use client";
import { pool } from "@/lib/db"; // csendes szivárgás 16 ban
// ...
// Javítás · markold a server only modult
// lib/db.ts
import "server-only"; // most már fordítási hibát dob, ha kliensből importálják
import { Pool } from "pg";
export const pool = new Pool();Egy SaaS dashboard nál a kliens JS bundle 940 kB ról 320 kB ra esett, miután mind a 6 szivárgást megtaláltuk. INP 380 ms ről 120 ms re.
033. Partial Prerendering ellen ható `dynamic = 'force-dynamic'`
A PPR (Partial Prerendering) 16 ban opt out, nem opt in. Ha bárhol az route segmentben van export const dynamic = 'force-dynamic', a teljes route kibukik a PPR ből, és minden request szerver oldalon teljesen renderelődik. Sok régi kódbázisban ez ott maradt egy korábbi debug ülésről.
// Audit script · keresd meg az összes force-dynamic t
// terminálban: grep -r "force-dynamic" src/app | wc -l
// ha > 5, valószínűleg fél tucatban feleslegesEgy magyar webshop projekten 14 db force-dynamic exportot találtunk. Hét volt indokolt (admin, fiók, kosár), hét felesleges (egy-egy debug ülésen valaki bedobta). A felesleges hét eltávolítása a TTFB t 280 ms ről 90 ms re vitte le a publikus oldalakon, mert a HTML újra cache elhetővé vált a Vercel edge n.
044. Képoptimalizálás · az új AVIF/JXL fallback rendje
A 16 ban a next/image beépített AVIF támogatást kapott (a 14 csak WebP volt default). A csapda: ha a next.config.ts ban a formats: ['image/webp'] ott maradt egy régebbi beállításból, az AVIF nem generálódik. Az új böngészők (97% lefedettség 2026 ban) AVIF re mennének, és 30-40% kal kisebb képet kapnának.
// next.config.ts
import type { NextConfig } from "next";
const config: NextConfig = {
images: {
formats: ["image/avif", "image/webp"], // sorrend számít
minimumCacheTTL: 60 * 60 * 24 * 30, // 30 nap
qualities: [40, 60, 80], // 16 új feature
},
};
export default config;Egy hírportál projekten az LCP 1.8s ről 1.1s re esett a fenti egyetlen config változással + a next/image quality={60} használattal a hero képeken.
055. Route segment config félreértés · a `revalidate` öröklődés
Ez a klasszikus, ami a 14 ben még meglepetést okozott, és a 16 ban is. Ha egy szülő layout ban export const revalidate = 60, és egy gyerek page ben export const revalidate = 3600, a gyerek értéke érvényesül · de csak a page.tsx re. A layout maga 60 másodpercen revalidálódik, és a gyerek page.tsx is, mert a layout cache invalidálása lehúzza a gyermeket is.
A javítás: ne tegyél revalidate t layoutba, ha nem akarod, hogy mindenre érvényes legyen. A pageonkénti finomhangolást a page.tsx ben tartsd.
Mind az 5 csapdát egy
next build && next startfutás közben fail2 grep el meg lehet találni. A bundle analyzer (@next/bundle-analyzer) plusz egy lighthouse audit elég. Ha a futási idő nem 2-3 nap, a saját kódbázisod nem ezekre szakad rá, hanem mélyebb dolgokra.
06Mit csinálj most
grep -r "force-dynamic" src/app | wc -l· ha 5 felett, audit szükséges.@next/bundle-analyzerfuttatása production buildben, kliens bundle > 350 kB ha · kliens szivárgás van.- Lighthouse / WebPageTest a 3 legfontosabb route on, LCP > 2.0s ha · use cache + Suspense interakció.
next.config.tsban formats szótár ellenőrzés, AVIF benne van e.- Layout fájlokban revalidate audit, csak ott legyen, ahol valóban kell.
Amit érdemes elvinni
- Öt Next.js 16 specifikus csapda, mind kódszintű, mind benne volt minden auditunkban. Use cache + suspense interakció, 'use client' boundary szivárgás, partial prerendering ellen ható dynamic IO, képoptimalizálás új formátum hiba, route segment config félreértés. Mindegyikhez mérési számok, javítás.
Az írásban használt fogalmak
Több a laborból
Összes bejegyzés
Core Web Vitals egy igazi Next.js oldalon- Server vs. kliens komponensek 2026: a döntési szabályunk
- Core Web Vitals Next.js-szel: hogyan lett 4.5s-ből 0.9s LCP
- htmx vs. React 2026-ban · kell-e tényleg SPA
Megnézzük ugyanezt a te rendszereden?Kezdjünk bele
