Live · status OK
Back to blog
Sviluppo12 min

Next.js static export e Core Web Vitals: il playbook 2026

TL;DR

Per raggiungere 95+ PageSpeed mobile su Next.js static export: self-host font via raw @font-face, preload font LCP con fetchPriority=high, evitare Framer Motion above-the-fold, usare solo transform/opacity per animazioni, riservare spazio layout per contenuto i18n, servire dietro Cloudflare free tier.

Julien Daniel
ByJulien Daniel
Founder & CTO, OptionWeb
Share
Dashboard PageSpeed Insights con punteggi prestazionali alti

Dopo 12 mesi di dati produzione su 40+ siti Next.js con static export, ecco il playbook esatto che applichiamo per raggiungere 95+ PageSpeed mobile. Nessuna teoria — solo ciò che funziona misurabilmente.

Baseline: cosa static export dà gratis

Un sito Next.js static export vaniglia punta 95-100 mobile perché tutto HTML pre-renderizzato, TTFB basso, nessun cold start. Aggiungendo Framer Motion, Google Fonts, icone, analytics, scendi a 70-85 senza accorgertene.

LCP: battaglia contro CSS render-blocking

Report PageSpeed mostrano stesso problema: due file CSS render-blocking aggiungono ~500ms render delay su mobile throttled. È 100% del budget LCP.

styles/globals.csscss
@font-face {
  font-family: 'Space Grotesk';
  font-weight: 500 700;
  font-display: swap;
  src: url('/fonts/space-grotesk-latin.woff2') format('woff2');
}

Strategia font che funziona

  • Display font (heading)1 variable font via raw @font-face, preload fetchPriority=high.
  • Body fontnext/font/google Inter con 2 pesi (400, 600), solo latin.
  • Monospacenext/font/google JetBrains Mono, preload=false.

INP: trappole Framer Motion

tsx
// ❌ Male
<motion.h1 initial={{ opacity: 0 }} animate={{ opacity: 1 }}>Titolo</motion.h1>

// ✅ Bene
<h1 className="ow-anim-fade-up">Titolo</h1>

Regole: mai animare width/height/top/left. Solo transform/opacity. Max 1-2 animazioni per viewport. useReducedMotion.

CLS: pattern riserva i18n

Su siti i18n, CLS appare quando traduzioni caricano dopo render iniziale. Soluzione: riservare min-height per breakpoint.

tsx
<div className="min-h-[280px] sm:min-h-[220px] md:min-h-[160px] lg:min-h-[130px]">
  <p>{t('tldr.content')}</p>
</div>

Immagini: AVIF, priority, fetchPriority

next.config.jsjs
images: { unoptimized: true, formats: ['image/avif', 'image/webp'] }

Hosting: Brotli 11, HTTP/3, Early Hints

  1. Host originqualsiasi host statico.
  2. Cloudflare free tier davantiHTTP/3, Brotli 11, edge cache.
  3. Early Hints (103)elimina wait TTFB dal critical path.
  4. Cache rule _next/static/*Cache Everything, Edge TTL 1 anno.
  5. Purge cache al deploywrangler o API Cloudflare in CI.

Come debuggare regressione PageSpeed

  1. Confronta reportquale metrica è scesa.
  2. Critical request chaincosa blocca ora il render.
  3. Chrome DevTools Performancelocalhost con throttling.
  4. Git diff depsnuovo pacchetto npm?
  5. next build outputrotta +20KB = sospetta.
Tags#nextjs#performance#core-web-vitals#pagespeed#framer-motion