React

Ottimizzare le immagini con next/image

Dimensioni, sizes, priority e formati: cosa fa next/image, cosa devi dichiarare tu e dove l’ottimizzazione si ferma.

In sintesi

  • `width` e `height` riservano lo spazio prima del download: è la difesa principale contro il layout shift.
  • `sizes` deve descrivere la larghezza reale dell’immagine, non la larghezza della finestra.
  • Una sola immagine `priority` per pagina, quella che misura l’LCP.

next/image risolve tre problemi: dichiarare le dimensioni prima del download, servire il formato e la larghezza giusti, e caricare tardi tutto tranne l’immagine principale. Se ne salti uno, l’ottimizzazione non si vede nei Core Web Vitals.

Dimensioni, sempre

import Image from "next/image";

export function Hero() {
  return (
    
  );
}

Con width e height il browser riserva lo spazio prima che il file arrivi: è la differenza tra un layout che salta e uno stabile. Il rapporto viene ricavato dai due numeri, non dal file scaricato, quindi il valore deve corrispondere alle proporzioni reali.

sizes decide quale file scarichi

Senza sizes, l’immagine viene trattata come larga quanto la finestra e il browser scarica il file più grande del necessario. Dichiara la larghezza reale che l’immagine occupa nel layout: una card in una griglia da tre colonne è un terzo, non il 100 per cento.


  

Con fill l’immagine occupa il contenitore: il contenitore deve essere posizionato e avere un’altezza, altrimenti l’altezza è zero e non si vede nulla. Un aspect-ratio esplicito evita di dipendere dal caricamento.

L’immagine LCP non si carica tardi

L’immagine più grande del primo schermo è quella che conta per LCP e non deve passare dal lazy loading. priority la precarica e alza la priorità della richiesta; nelle versioni più recenti la prop si chiama preload. Una sola immagine per pagina: metterla su tutte annulla l’effetto e toglie banda alle altre.

Cosa risponde l’optimizer

In sviluppo e in produzione l’immagine non viene servita dal percorso originale ma da un endpoint che ridimensiona e riconverte. La risposta dice il formato scelto e la cache applicata: è il modo più rapido per capire se l’ottimizzazione sta girando.

curl -sI "http://localhost:3000/_next/image?url=%2Fhero.jpg&w=640&q=75"

Formati e domini esterni

AVIF pesa meno di WebP e WebP meno di JPEG; il browser sceglie dal formato che gli offri. Per le immagini su un dominio esterno serve remotePatterns: senza, la richiesta viene rifiutata e l’immagine non compare. Un SVG non ha bisogno di essere riconvertito: unoptimized evita un passaggio inutile.

// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  images: {
    formats: ["image/avif", "image/webp"],
    remotePatterns: [
      { protocol: "https", hostname: "images.example.com" },
    ],
  },
};

export default nextConfig;

Il costo, misurato

Le cover degli articoli di questo sito sono PNG generati e serviti così come sono, perché li leggono anche gli scraper dei social. La media dice che una cover sta sotto i 100 KB: accettabile per un’anteprima, da riconvertire per un’immagine in pagina.

Le gallerie hanno bisogno di proporzioni stabili prima che le immagini arrivino: il record Gallery 4 mostra una griglia già composta, Image Comparison Slider un caso con due immagini sovrapposte, e i blocchi hero il punto in cui l’immagine LCP vive. Il codice arriva nel tuo repository: le dimensioni le dichiari tu.

Errori che si vedono in produzione

  • Mettere width e height sbagliati per non toccare il CSS: il rapporto resta sbagliato e il CLS pure.
  • Usare fill dentro un contenitore senza posizione: l’immagine collassa a zero pixel.
  • priority su ogni immagine della pagina: nessuna è più prioritaria e la banda si divide.
  • unoptimized globale per far sparire un errore di remotePatterns: si perde tutto il vantaggio.

Un limite da dichiarare

Con output: "export" l’optimizer non esiste: next/image si riduce a un tag img e i formati alternativi li devi servire tu. Lo stesso vale se il sito sta dietro una CDN che non lascia passare l’endpoint /_next/image: in quel caso configura il loader, non spegnere l’ottimizzazione.

Il legame tra immagini e layout shift è spiegato in layout shift e immagini senza dimensioni; le soglie da rispettare sono in cosa sono i Core Web Vitals. Se stai scegliendo il framework, Astro vs Next.js confronta due modi opposti di trattare le immagini.

Domande frequenti

next/image serve anche per le icone SVG?

No. Un SVG non ha bisogno di ridimensionamento: usa un tag img, oppure passa unoptimized per evitare una conversione inutile.

Perché l’immagine non si vede con fill?

Perché il contenitore non è posizionato o non ha altezza. Aggiungi position relative e un aspect-ratio al contenitore.

Quante immagini posso marcare priority?

Una, quella più grande sopra la piega. Con due o più la priorità si annulla e il browser scarica tutto insieme.

Quale formato conviene tra AVIF e WebP?

AVIF pesa meno, WebP si decodifica più in fretta su hardware vecchio. Offri entrambi e lascia scegliere al browser.

Posso usare next/image con un URL esterno?

Sì, dopo aver aggiunto il dominio in remotePatterns nella configurazione delle immagini. Senza quella voce la richiesta viene rifiutata.