Next.js static export en Core Web Vitals: het 2026 playbook
Om 95+ PageSpeed mobiel op Next.js static export te halen: self-host fonts via raw @font-face, preload de LCP-font met fetchPriority=high, vermijd Framer Motion above-the-fold, gebruik alleen transform/opacity voor animaties, reserveer layout-ruimte voor i18n-content, serveer via Cloudflare free tier.
Na 12 maanden productiedata op 40+ Next.js sites met static export, hier het exacte playbook dat we toepassen om 95+ PageSpeed mobiel te halen. Geen theorie — alleen wat meetbaar werkt.
Baseline: wat static export je gratis geeft
Een vanilla Next.js static export site scoort 95-100 mobiel omdat alle HTML pre-rendered is, lage TTFB, geen cold starts, automatische code splitting. Zodra je Framer Motion, Google Fonts, iconen, analytics toevoegt, daal je naar 70-85 zonder het te beseffen.
LCP: de strijd tegen render-blocking CSS
PageSpeed-rapporten tonen hetzelfde probleem: twee render-blocking CSS-bestanden (Tailwind + next/font Google) voegen ~500ms render delay toe op mobile throttled. Dat is 100% van het LCP-budget.
@font-face {
font-family: 'Space Grotesk';
font-style: normal;
font-weight: 500 700;
font-display: swap;
src: url('/fonts/space-grotesk-latin.woff2') format('woff2');
}Font-strategie die echt werkt
- Display font (headings) — 1 variable font via raw @font-face, range 500-700, preload fetchPriority=high.
- Body font — next/font/google Inter met 2 weights (400, 600), alleen latin.
- Monospace — next/font/google JetBrains Mono, 1 weight, preload=false.
INP: Framer Motion valkuilen
INP verving FID maart 2024, veel strikter. Boven 200ms = 'poor'. Framer Motion vaak de schuldige.
// ❌ Slecht: vertraagt LCP
<motion.h1 initial={{ opacity: 0 }} animate={{ opacity: 1 }}>Titel</motion.h1>
// ✅ Goed: CSS keyframe, geen JS-vertraging
<h1 className="ow-anim-fade-up">Titel</h1>Regels: nooit width/height/top/left animeren (layout reflow). Alleen transform/opacity. Max 1-2 animaties per viewport. Altijd useReducedMotion gebruiken.
CLS: i18n-reserveringspatroon
Op i18n-sites verschijnt CLS wanneer vertalingen laden na initial render. Oplossing: reserveer min-height per breakpoint.
<div className="min-h-[280px] sm:min-h-[220px] md:min-h-[160px] lg:min-h-[130px]">
<p>{t('tldr.content')}</p>
</div>Afbeeldingen: AVIF, priority, fetchPriority
images: {
unoptimized: true,
formats: ['image/avif', 'image/webp'],
}Hosting: Brotli 11, HTTP/3, Early Hints
- Origin host — elke statische host.
- Cloudflare free tier vooraan — HTTP/3, Brotli 11, edge cache.
- Early Hints (103) — elimineert TTFB wait van critical path.
- Cache rule _next/static/* — Cache Everything, Edge TTL 1 jaar.
- Purge cache on deploy — wrangler of Cloudflare API in CI.
Hoe PageSpeed regressie debuggen
- Vergelijk PageSpeed rapporten — welke metriek is gedaald.
- Critical request chain — wat blokkeert nu het renderen.
- Chrome DevTools Performance — localhost met throttling.
- Git diff deps — nieuw npm package?
- Check next build output — route +20KB = verdacht.
