Live · status OK
Back to blog
Desenvolvimento12 min

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

TL;DR

Para atingir 95+ PageSpeed mobile em Next.js static export: auto-hospedar fontes via raw @font-face, precarregar fonte LCP com fetchPriority=high, evitar Framer Motion above-the-fold, usar apenas transform/opacity para animações, reservar espaço layout para conteúdo i18n, servir atrás de Cloudflare free tier.

Julien Daniel
ByJulien Daniel
Founder & CTO, OptionWeb
Share
Dashboard PageSpeed Insights com pontuações altas

Após 12 meses de dados de produção em 40+ sites Next.js com static export, eis o playbook exato que aplicamos para atingir 95+ PageSpeed mobile. Sem teoria — apenas o que funciona mensuravelmente.

Baseline: o que static export dá grátis

Um site Next.js static export baunilha pontua 95-100 mobile porque todo HTML está pré-renderizado, TTFB baixo, sem cold starts. Ao adicionar Framer Motion, Google Fonts, ícones, analytics, cai para 70-85.

LCP: batalha contra CSS render-blocking

Relatórios PageSpeed mostram o mesmo problema: dois ficheiros CSS render-blocking adicionam ~500ms render delay em mobile throttled. É 100% do orçamento 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');
}

Estratégia de fontes que realmente funciona

  • Fonte display (headings)1 variable font via raw @font-face, preload fetchPriority=high.
  • Fonte bodynext/font/google Inter com 2 pesos (400, 600), apenas latin.
  • Monospacenext/font/google JetBrains Mono, preload=false.

INP: armadilhas Framer Motion

tsx
// ❌ Mau
<motion.h1 initial={{ opacity: 0 }} animate={{ opacity: 1 }}>Título</motion.h1>

// ✅ Bom
<h1 className="ow-anim-fade-up">Título</h1>

Regras: nunca animar width/height/top/left. Apenas transform/opacity. Max 1-2 animações por viewport. useReducedMotion.

CLS: padrão reserva i18n

Em sites i18n, CLS aparece quando traduções carregam após render inicial. Solução: reservar min-height por 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>

Imagens: AVIF, priority, fetchPriority

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

Hosting: Brotli 11, HTTP/3, Early Hints

  1. Host origemqualquer host estático.
  2. Cloudflare free tier à frenteHTTP/3, Brotli 11, edge cache.
  3. Early Hints (103)elimina wait TTFB do critical path.
  4. Cache rule _next/static/*Cache Everything, Edge TTL 1 ano.
  5. Purge cache no deploywrangler ou API Cloudflare em CI.

Como debugar regressão PageSpeed

  1. Comparar relatóriosqual métrica caiu.
  2. Critical request chaino que bloqueia agora o render.
  3. Chrome DevTools Performancelocalhost com throttling.
  4. Git diff depsnovo pacote npm?
  5. next build outputrota +20KB = suspeita.
Tags#nextjs#performance#core-web-vitals#pagespeed#framer-motion