Otimização de Imagens no Next.js para Core Web Vitals em 2026

Passei os últimos quatro anos otimizando imagens em apps Next.js, e vou ser honesto -- o cenário em 2026 é completamente diferente de quando next/image foi lançado. Os limites do Core Web Vitals do Google ficaram mais rigorosos, novos formatos de imagem amadureceram, e o componente next/image passou por múltiplas reescritas. Se suas imagens ainda estão configuradas do jeito que eram em 2023, você está deixando performance (e rankings) na mesa.

Isso não é um resumo da documentação do Next.js. É o que aprendi ao colocar em produção dezenas de sites onde os scores de LCP realmente importam -- onde uma diferença de 200ms no carregamento de imagens significou a diferença entre página um e página três.

Índice

Otimização de Imagens no Next.js para Core Web Vitals em 2026

Core Web Vitals em 2026: O Que Mudou

Google atualizou os limites do Core Web Vitals no final de 2025, e as mudanças não foram triviais. Aqui está como as coisas estão:

Métrica Limite "Bom" 2023 Limite "Bom" 2026 O Que Mede
LCP ≤ 2.5s ≤ 2.0s Largest Contentful Paint
INP ≤ 200ms ≤ 150ms Interaction to Next Paint
CLS ≤ 0.1 ≤ 0.1 Cumulative Layout Shift
TTFB N/A (não é CWV) Informalmente ≤ 600ms Time to First Byte

O limite do LCP caindo de 2.5s para 2.0s foi o que mais afetou sites com muitas imagens. Meio segundo não parece muito até você perceber que em 60%+ das páginas, o elemento LCP é uma imagem. Geralmente uma imagem hero, uma foto de produto ou uma miniatura de artigo em destaque.

O INP substituindo o FID já estava em vigor, mas o limite reduzido de 150ms significa que grandes bundles de JavaScript -- incluindo scripts de lazy-loading de imagem mal configurados -- podem prejudicar seus scores de interatividade.

CLS permaneceu o mesmo, o que é uma boa notícia. Mas imagens continuam sendo a causa número um de layout shift quando não têm dimensões explícitas.

Por Que Isso Importa Especificamente para Next.js

Apps Next.js tendem a ser pesados em JavaScript por natureza. Você está enviando React, está enviando código do framework, e se não tomar cuidado, está enviando lógica de otimização de imagem no lado do cliente também. A combinação de um orçamento LCP mais restrito e o overhead de JS de um app React significa que você tem menos espaço para erros do que um site HTML estático.

É exatamente por isso que nos focamos fortemente em desenvolvimento Next.js -- o framework oferece ferramentas incríveis, mas apenas se você souber como configurá-las.

Como next/image Realmente Funciona Internamente

Vamos desmistificar o que acontece quando você usa <Image /> de next/image. Entender o pipeline ajuda você a tomar melhores decisões de otimização.

O Fluxo de Requisição

  1. Tempo de build: Next.js gera HTML com uma tag <img> que aponta para /_next/image?url=...&w=...&q=...
  2. Primeira requisição: A API de otimização de imagem do Next.js recebe a requisição, busca a imagem original, redimensiona, converte o formato e armazena em cache o resultado
  3. Requisições subsequentes: A versão em cache é servida diretamente

No Next.js 15 (o estável atual no início de 2026), o otimizador de imagem usa sharp por padrão em ambientes Node.js. No Vercel, usa seu serviço de otimização de imagem baseado em edge. Em outras plataformas, volta para sharp ou squoosh dependendo de sua configuração.

// Uso básico -- mas muita coisa está acontecendo por trás disso
import Image from 'next/image';

export default function Hero() {
  return (
    <Image
      src="/hero.jpg"
      alt="Foto hero do produto"
      width={1200}
      height={630}
      priority
      quality={80}
    />
  );
}

Esse prop priority está fazendo mais do que você pensa. Ele adiciona fetchpriority="high" ao HTML, desativa lazy loading e gera uma tag <link> de preload no <head>. Voltaremos a por que isso importa para LCP.

A Config Que a Maioria das Pessoas Nunca Toca

Seu next.config.js (ou next.config.ts se você migrou) tem uma chave images que controla tudo:

// next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048],
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    minimumCacheTTL: 31536000, // 1 ano em segundos
    dangerouslyAllowSVG: false,
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'your-cms.com',
        pathname: '/assets/**',
      },
    ],
  },
};

A ordem do array formats importa. Next.js tentará AVIF primeiro, depois volta para WebP. Codificação AVIF é mais lenta mas produz arquivos menores -- esse trade-off é importante entender.

O Problema do LCP: Por Que Sua Imagem Hero Está Matando Seu Score

Aqui está o cenário que vejo em quase toda auditoria: uma linda imagem hero, acima da dobra, que leva 3+ segundos para renderizar. O desenvolvedor usou next/image, achou que tinha terminado e seguiu em frente. Mas o score é terrível.

Os culpados usuais:

1. Faltando o Prop `priority`

Por padrão, next/image faz lazy-loading de tudo. Isso é ótimo para imagens abaixo da dobra mas catastrófico para seu elemento LCP. Sem priority, o navegador descobre a imagem tarde, após o JavaScript ter sido hidratado e o intersection observer ter começado a funcionar.

// ❌ Isso faz lazy-loading de sua imagem LCP
<Image src="/hero.jpg" alt="Hero" width={1200} height={630} />

// ✅ Isso faz preload
<Image src="/hero.jpg" alt="Hero" width={1200} height={630} priority />

2. Sobre-compressão com Valores de Qualidade Baixos

Já vi times configurarem quality={50} pensando que menor = mais rápido. Mas se a imagem fica desfocada, o algoritmo de LCP do Chrome ainda precisa esperar que ela renderize completamente. E em telas de alta DPI, qualidade abaixo de 70 frequentemente dispara artefatos visíveis que fazem o design parecer barato.

Minha regra de ouro: qualidade 75-85 para fotos, qualidade 90+ para imagens com texto ou arestas nítidas.

3. Não Usando `sizes` Corretamente

O atributo sizes diz ao navegador qual largura de imagem requisitar antes do CSS ser parseado. Sem ele, Next.js usa o padrão 100vw, o que significa que dispositivos móveis baixam imagens do tamanho desktop.

<Image
  src="/hero.jpg"
  alt="Hero"
  fill
  priority
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px"
/>

Essa mudança em um único prop me deu as maiores melhorias de LCP -- às vezes 400-800ms em mobile.

Otimização de Imagens no Next.js para Core Web Vitals em 2026 - arquitetura

Guerra de Formatos: AVIF vs WebP vs JPEG XL em 2026

A paisagem de formatos se estabeleceu bastante. Aqui está onde estamos:

Formato Suporte de Navegador (2026) Compressão Velocidade de Codificação Melhor Para
AVIF ~95% globalmente Excelente (30-50% menor que WebP) Lenta Fotos, imagens hero
WebP ~98% globalmente Bom (25-35% menor que JPEG) Rápida Uso geral
JPEG XL ~45% (Chrome removeu) Excelente Média Não recomendado para web
JPEG Universal Baseline Rápida Apenas fallback
PNG Universal Pobre para fotos Rápida Transparência, screenshots

JPEG XL tinha uma especificação promissora, mas a decisão do Chrome de remover suporte no final de 2023 o matou efetivamente para uso web. Safari adicionou suporte, Firefox tem suporte parcial, mas você não pode contar com isso.

Minha recomendação: Defina formats: ['image/avif', 'image/webp'] e esqueça sobre isso. Next.js lida com negociação de conteúdo via o header Accept automaticamente.

O Custo de Codificação AVIF

Aqui está algo que a documentação não enfatiza o suficiente: a codificação AVIF é computacionalmente intensiva. Na primeira requisição ao seu servidor Next.js, codificar uma imagem AVIF de 1200px pode levar 2-5 segundos em um servidor modesto. Esse primeiro visitante paga o custo.

Estratégias para mitigar isso:

  • Pré-gerar no tempo de build usando next export ou scripts de build customizados
  • Usar um CDN com otimização de imagem integrada (Cloudflare Images, Imgix, Cloudinary)
  • Aquecer seu cache após deployment com um script que acessa todas as URLs de imagem crítica
# Script simples de aquecimento de cache
#!/bin/bash
URLs=("https://yoursite.com/_next/image?url=%2Fhero.jpg&w=1200&q=80"
      "https://yoursite.com/_next/image?url=%2Fhero.jpg&w=750&q=80")

for url in "${URLs[@]}"; do
  curl -s -o /dev/null -H "Accept: image/avif,image/webp" "$url"
  echo "Aquecido: $url"
done

Imagens Responsivas Feitas Corretamente

Imagens responsivas no Next.js não são difíceis, mas requerem entender como deviceSizes, imageSizes e o prop sizes funcionam juntos.

O Padrão de Layout `fill`

Para imagens onde você não sabe a taxa de aspecto no tempo de build (conteúdo de CMS, uploads de usuário), use o prop fill:

<div className="relative aspect-[16/9] w-full">
  <Image
    src={post.featuredImage}
    alt={post.title}
    fill
    className="object-cover"
    sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
  />
</div>

A div pai com posicionamento relative e uma taxa de aspecto é crítica. Sem isso, imagens fill desabam para altura zero e você terá um score CLS que vai fazer você morder a bochecha.

Direção de Arte com ``

Às vezes você precisa de recortes diferentes para diferentes tamanhos de tela. next/image não suporta <picture> nativamente, mas você pode trabalhar em torno disso:

// Workaround de direção de arte
export function ResponsiveHero({ mobileSrc, desktopSrc, alt }) {
  return (
    <>
      <div className="block md:hidden relative aspect-[9/16] w-full">
        <Image src={mobileSrc} alt={alt} fill priority sizes="100vw" />
      </div>
      <div className="hidden md:block relative aspect-[16/9] w-full">
        <Image src={desktopSrc} alt={alt} fill priority sizes="100vw" />
      </div>
    </>
  );
}

Sim, isso baixa ambas as imagens no HTML, mas apenas uma renderiza, e a oculta não carregará graças aos padrões de lazy loading (você aplicaria priority apenas à que corresponde ao viewport).

Estratégias de Otimização de CDN e Edge

Se você está auto-hospedando Next.js (e muitos times estão), você precisa de uma estratégia de CDN para imagens.

Opção 1: Deixe Vercel Cuidar Disso

A otimização de imagem do Vercel roda na edge. Para a maioria dos projetos, esse é o caminho mais fácil. A partir de 2026, o plano Pro do Vercel inclui 5.000 imagens de origem com otimização, com imagens adicionais a $5 por 1.000. Planos Enterprise têm preço customizado.

Opção 2: Serviço Externo de Otimização de Imagem

Cloudinary, Imgix e Cloudflare Images funcionam com Next.js através do prop loader ou um loader customizado:

// next.config.js com Cloudinary
module.exports = {
  images: {
    loader: 'custom',
    loaderFile: './lib/cloudinary-loader.js',
  },
};
// lib/cloudinary-loader.js
export default function cloudinaryLoader({ src, width, quality }) {
  const params = [
    `w_${width}`,
    `q_${quality || 'auto'}`,
    'f_auto',
    'c_limit',
  ];
  return `https://res.cloudinary.com/your-cloud/image/upload/${params.join(',')}${src}`;
}
Serviço Tier Gratuito Preço Pro (2026) Nós de Edge Suporte AVIF
Cloudinary 25 créditos/mês $89/mês (25GB) 60+ Sim
Imgix Nenhum $100/mês (100GB) Global Sim
Cloudflare Images Nenhum $5/mês (100K variações) 310+ Sim
Vercel (integrado) 1.000 imagens (Hobby) Incluído no Pro Edge Sim

Para nossos projetos de desenvolvimento de CMS headless, normalmente usamos Cloudinary ou o pipeline de imagem integrado do CMS (Sanity, Contentful e Hygraph todos têm APIs de imagem decentes).

Opção 3: Cloudflare Polish + Next.js

Se você já está atrás de Cloudflare, o recurso Polish deles pode lidar com conversão de formato na edge. Você desabilitaria a otimização de imagem do Next.js e deixaria Cloudflare fazer o trabalho:

module.exports = {
  images: {
    unoptimized: true, // Deixe Cloudflare cuidar disso
  },
};

Não sou grande fã dessa abordagem porque você perde o dimensionamento responsivo que next/image oferece, mas funciona para setups mais simples.

Medindo o Que Importa: Ferramentas e Benchmarks

Você não pode melhorar o que não mede. Aqui está minha pilha de testes:

Ferramentas de Lab

  • Chrome DevTools Lighthouse (v12 a partir de 2026): Ainda o ponto de partida. Execute em incógnito sem extensões.
  • WebPageTest: Configure para Dulles, VA em um Moto G Power com 4G. Isso representa um usuário realista "lento".
  • Unlighthouse: Escaneia em massa seu site inteiro. Incrível para pegar páginas que você esqueceu.

Dados de Campo

  • Chrome UX Report (CrUX): Os dados reais que Google usa para sinais de ranking. Disponível em PageSpeed Insights e BigQuery.
  • web-vitals.js: Adicione ao seu app para coletar métricas de usuário real:
// app/layout.tsx
import { onLCP, onINP, onCLS } from 'web-vitals';

if (typeof window !== 'undefined') {
  onLCP(console.log);
  onINP(console.log);
  onCLS(console.log);
}

Em produção, envie esses para sua plataforma de analytics em vez de console.log. Usamos uma combinação de Vercel Speed Insights e um endpoint customizado que escreve para BigQuery.

Alvos de Benchmark para 2026

Baseado nos sites que auditamos este ano, aqui está como "bom" se parece para sites Next.js pesados em imagem:

  • LCP em mobile (p75): < 1.8s (oferece buffer sob o limite de 2.0s)
  • Peso total de imagem acima da dobra: < 200KB
  • Tempo de carregamento de imagem hero: < 800ms em 4G
  • CLS de imagens: 0

Técnicas Avançadas Que Realmente Fazem Diferença

Placeholders Desfocados com BlurHash

Next.js suporta placeholder="blur" nativamente para imports estáticos. Para imagens dinâmicas (de um CMS), você precisará gerar URLs de dados blur:

import { getPlaiceholder } from 'plaiceholder';

export async function getStaticProps() {
  const { base64 } = await getPlaiceholder('/path/to/image.jpg');
  return {
    props: { blurDataURL: base64 },
  };
}

// No componente
<Image
  src={dynamicUrl}
  alt="Imagem dinâmica"
  fill
  placeholder="blur"
  blurDataURL={blurDataURL}
/>

Isso não melhora LCP diretamente, mas melhora dramaticamente a performance percebida e evita CLS.

HTTP/3 e Early Hints

Se seu CDN suporta HTTP/3 (Cloudflare, Fastly e Vercel todos suportam), você pode usar 103 Early Hints para começar a enviar a imagem LCP antes do documento HTML estar completamente gerado:

// middleware.ts
import { NextResponse } from 'next/server';

export function middleware(request) {
  const response = NextResponse.next();
  
  if (request.nextUrl.pathname === '/') {
    response.headers.set(
      'Link',
      '</hero.avif>; rel=preload; as=image; type="image/avif"'
    );
  }
  
  return response;
}

Carregamento de Skeleton com CSS `content-visibility`

Para páginas longas com muitas imagens, content-visibility: auto diz ao navegador para pular renderização de conteúdo fora da tela completamente:

.image-grid-item {
  content-visibility: auto;
  contain-intrinsic-size: 300px 200px; /* Tamanho estimado */
}

Isso reduz INP por 30-40ms em uma página de listagem de produtos que otimizamos no trimestre passado.

Erros Comuns Que Vejo em Toda Auditoria

  1. Usar next/image para SVGs decorativos: Apenas use uma tag <img> ou inline o SVG. O pipeline de otimização adiciona overhead sem benefício.

  2. Configurar unoptimized globalmente porque "imagens ficam desfocadas": Arrume a configuração de qualidade em vez disso. unoptimized ignora tudo.

  3. Esquecer texto alt: Isso não é apenas acessibilidade -- busca de imagem do Google conduz tráfego, e precisa de texto alt para indexar suas imagens.

  4. Não configurar minimumCacheTTL: O padrão é 60 segundos. Isso significa que seu servidor re-otimiza a mesma imagem a cada minuto sob carga. Configure para pelo menos 2592000 (30 dias).

  5. Usar imagens fonte massivas: Subir uma foto de DSLR 6000x4000px e esperar que Next.js cuide disso. Pré-processe suas imagens fonte para um máximo de 2x seu maior tamanho de exibição.

  6. Ignorar a aba Network: Abra DevTools, filtre por Img, ordene por tamanho. Você encontrará problemas em 30 segundos.

Se você está lutando com esses problemas em um site em produção, esse é exatamente o tipo de problema que resolvemos. Confira nosso pricing ou entre em contato direto -- fazemos auditorias de performance como engajamentos standalone.

FAQ

next/image converte imagens para AVIF automaticamente?

Sim, se você tiver 'image/avif' em seu array images.formats em next.config.js (está incluído por padrão desde Next.js 14). A conversão acontece sob demanda quando um navegador envia um header Accept que inclui image/avif. A primeira requisição é mais lenta devido a codificação, mas requisições subsequentes são servidas de cache.

Quanto AVIF realmente reduz o tamanho de arquivo de imagem comparado a WebP?

Em nossos testes em centenas de imagens em produção, AVIF tem em média 30-50% menor que WebP em qualidade visual equivalente, e 50-70% menor que JPEG. Os ganhos são mais dramáticos em conteúdo fotográfico. Para screenshots ou imagens com texto, a diferença reduz para 15-25%.

Devo usar priority em múltiplas imagens? Use raramente -- apenas em imagens que estão genuinamente acima da dobra e visíveis no carregamento inicial. Adicionar priority a mais de 2-3 imagens anula o propósito porque o navegador não pode priorizar tudo simultaneamente. Para sua imagem hero da homepage e talvez um logo, é isso.

Por que meu LCP ainda está lento mesmo com next/image e priority?

A razão mais comum é que seu tempo de resposta do servidor (TTFB) está comendo seu orçamento. Se seu servidor Next.js leva 800ms para responder, você só tem 1.2 segundos restante para a imagem carregar e renderizar. Outros culpados: CSS que bloqueia render, grandes bundles de JavaScript que atrasam hidratação, ou a origem da imagem sendo lenta.

Posso usar next/image com static exports (next export)?

Não com otimização integrada. Static exports requerem images.unoptimized: true ou um loader customizado apontando para um serviço externo como Cloudinary ou Imgix. Essa é uma razão pela qual às vezes recomendamos Astro para sites puramente estáticos -- seu tratamento de imagem não requer um servidor rodando.

Como faço para lidar com imagens de um CMS headless com next/image?

Adicione o domínio de imagem do CMS a images.remotePatterns em sua config. A maioria das plataformas de CMS headless (Sanity, Contentful, Storyblok, Hygraph) têm suas próprias APIs de transformação de imagem. Você pode usar essas via um loader customizado ou deixar Next.js cuidar da otimização. Geralmente preferimos o pipeline nativo do CMS para projetos de CMS headless porque reduz carga do servidor.

Qual é o impacto da otimização de imagem nos sinais de ranking do Core Web Vitals?

Google confirmou em 2025 que Core Web Vitals permanece um sinal de ranking, embora relevância de conteúdo ainda domine. Dito isso, para queries competitivas onde qualidade de conteúdo é similar nos principais resultados, CWV pode ser o desempate. Vimos sites se moverem 3-8 posições após corrigir problemas de LCP que foram principalmente causados por imagens não otimizadas.

Devo fazer lazy-load de todas as imagens abaixo da dobra?

Sim, e Next.js faz isso por padrão (a menos que você adicione priority). O atributo nativo loading="lazy" é o que next/image usa internamente. Não há necessidade de uma biblioteca de lazy loading baseada em JavaScript -- lazy loading nativo do navegador tem sido estável em todos os navegadores principais desde 2022.