Optimisation des images

Exemples

Selon le Web Almanac, les images représentent une part importante du poids de page d'un site web typique et peuvent avoir un impact significatif sur les performances LCP de votre site.

Le composant Image de Next.js étend l'élément HTML <img> avec des fonctionnalités d'optimisation automatique des images :

  • Optimisation de taille : Servir automatiquement des images de la bonne taille pour chaque appareil, en utilisant des formats modernes comme WebP et AVIF.
  • Stabilité visuelle : Empêcher automatiquement les décalages de mise en page lors du chargement des images.
  • Chargement plus rapide : Les images ne sont chargées que lorsqu'elles entrent dans le viewport grâce au lazy loading natif du navigateur, avec des placeholders floutés optionnels.
  • Flexibilité des assets : Redimensionnement des images à la demande, même pour les images stockées sur des serveurs distants.

🎥 Regarder : En savoir plus sur l'utilisation de next/imageYouTube (9 minutes).

Utilisation

import Image from 'next/image'

Vous pouvez ensuite définir le src pour votre image (locale ou distante).

Images locales

Pour utiliser une image locale, importez vos fichiers .jpg, .png ou .webp.

Next.js déterminera automatiquement la width et la height de votre image en fonction du fichier importé. Ces valeurs sont utilisées pour éviter les décalages de mise en page cumulatifs pendant le chargement de votre image.

app/page.js
import Image from 'next/image'
import profilePic from './me.png'

export default function Page() {
  return (
    <Image
      src={profilePic}
      alt="Photo de l'auteur"
      // width={500} fourni automatiquement
      // height={500} fourni automatiquement
      // blurDataURL="data:..." fourni automatiquement
      // placeholder="blur" // Flou optionnel pendant le chargement
    />
  )
}

Avertissement : Les imports dynamiques await import() ou require() ne sont pas supportés. L'import doit être statique pour pouvoir être analysé au moment de la construction.

Vous pouvez optionnellement configurer localPatterns dans votre fichier next.config.js pour autoriser des images spécifiques et bloquer toutes les autres.

next.config.js
module.exports = {
  images: {
    localPatterns: [
      {
        pathname: '/assets/images/**',
        search: '',
      },
    ],
  },
}

Images distantes

Pour utiliser une image distante, la propriété src doit être une URL sous forme de chaîne.

Comme Next.js n'a pas accès aux fichiers distants pendant la construction, vous devrez fournir manuellement les props width, height et optionnellement blurDataURL.

Les attributs width et height sont utilisés pour déduire le bon ratio d'aspect de l'image et éviter les décalages de mise en page lors du chargement. La width et la height ne déterminent pas la taille de rendu du fichier image. En savoir plus sur le dimensionnement des images.

app/page.js
import Image from 'next/image'

export default function Page() {
  return (
    <Image
      src="https://s3.amazonaws.com/my-bucket/profile.png"
      alt="Photo de l'auteur"
      width={500}
      height={500}
    />
  )
}

Pour autoriser en toute sécurité l'optimisation des images, définissez une liste de modèles d'URL supportés dans next.config.js. Soyez aussi spécifique que possible pour éviter les utilisations malveillantes. Par exemple, la configuration suivante n'autorisera que les images provenant d'un bucket AWS S3 spécifique :

next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 's3.amazonaws.com',
        port: '',
        pathname: '/my-bucket/**',
        search: '',
      },
    ],
  },
}

En savoir plus sur la configuration remotePatterns. Si vous souhaitez utiliser des URLs relatives pour le src de l'image, utilisez un loader.

Domaines

Parfois, vous pouvez vouloir optimiser une image distante tout en utilisant l'API d'optimisation d'images intégrée à Next.js. Pour ce faire, laissez le loader à sa valeur par défaut et entrez une URL absolue pour la prop src de l'Image.

Pour protéger votre application contre les utilisateurs malveillants, vous devez définir une liste de noms d'hôtes distants que vous comptez utiliser avec le composant next/image.

En savoir plus sur la configuration remotePatterns.

Loaders

Notez que dans l'exemple précédent, une URL partielle ("/me.png") est fournie pour une image locale. Ceci est possible grâce à l'architecture des loaders.

Un loader est une fonction qui génère les URLs pour votre image. Il modifie le src fourni et génère plusieurs URLs pour demander l'image à différentes tailles. Ces multiples URLs sont utilisées dans la génération automatique du srcset, afin que les visiteurs de votre site reçoivent une image de la bonne taille pour leur viewport.

Le loader par défaut pour les applications Next.js utilise l'API d'optimisation d'images intégrée, qui optimise les images depuis n'importe où sur le web, puis les sert directement depuis le serveur web Next.js. Si vous souhaitez servir vos images directement depuis un CDN ou un serveur d'images, vous pouvez écrire votre propre fonction loader avec quelques lignes de JavaScript.

Vous pouvez définir un loader par image avec la prop loader, ou au niveau de l'application avec la configuration loaderFile.

Priorité

Vous devriez ajouter la propriété priority à l'image qui sera l'élément Largest Contentful Paint (LCP) pour chaque page. Cela permet à Next.js de prioriser spécifiquement le chargement de l'image (par exemple via des balises preload ou des priority hints), ce qui améliore significativement le LCP.

L'élément LCP est généralement la plus grande image ou bloc de texte visible dans le viewport de la page. Lorsque vous exécutez next dev, vous verrez un avertissement dans la console si l'élément LCP est une <Image> sans la propriété priority.

Une fois que vous avez identifié l'image LCP, vous pouvez ajouter la propriété comme ceci :

app/page.js
import Image from 'next/image"
import profilePic from '../public/me.png'

export default function Page() {
  return <Image src={profilePic} alt="Photo de l'auteur" priority />
}

Voir plus sur la priorité dans la documentation du composant next/image.

Dimensionnement des images

L'une des façons dont les images nuisent le plus souvent aux performances est par le biais des décalages de mise en page, où l'image repousse d'autres éléments de la page pendant son chargement. Ce problème de performance est si gênant pour les utilisateurs qu'il a sa propre Core Web Vital, appelée Cumulative Layout Shift. La façon d'éviter les décalages de mise en page liés aux images est de toujours dimensionner vos images. Cela permet au navigateur de réserver précisément assez d'espace pour l'image avant son chargement.

Comme next/image est conçu pour garantir de bons résultats de performance, il ne peut pas être utilisé d'une manière qui contribuerait aux décalages de mise en page, et doit être dimensionné de l'une des trois manières suivantes :

  1. Automatiquement, en utilisant un import statique
  2. Explicitement, en incluant une propriété width et height
  3. Implicitement, en utilisant fill qui fait que l'image s'étend pour remplir son élément parent.

Que faire si je ne connais pas la taille de mes images ?

Si vous accédez à des images depuis une source sans connaissance de leurs tailles, voici plusieurs options :

Utiliser fill

La prop fill permet à votre image d'être dimensionnée par son élément parent. Pensez à utiliser CSS pour donner à l'élément parent de l'image de l'espace sur la page avec la prop sizes pour correspondre à tout point de rupture de média query. Vous pouvez aussi utiliser object-fit avec fill, contain ou cover, et object-position pour définir comment l'image doit occuper cet espace.

Normaliser vos images

Si vous servez des images depuis une source que vous contrôlez, envisagez de modifier votre pipeline d'images pour normaliser les images à une taille spécifique.

Modifier vos appels API

Si votre application récupère des URLs d'images via un appel API (comme vers un CMS), vous pourriez modifier l'appel API pour retourner les dimensions de l'image avec l'URL.

Si aucune de ces méthodes suggérées ne fonctionne pour dimensionner vos images, le composant next/image est conçu pour fonctionner correctement sur une page aux côtés d'éléments <img> standards.

Stylisation

Styliser le composant Image est similaire à styliser un élément <img> normal, mais il y a quelques directives à garder à l'esprit :

  • Utilisez className ou style, pas styled-jsx.
    • Dans la plupart des cas, nous recommandons d'utiliser la prop className. Cela peut être un CSS Module importé, une feuille de style globale, etc.
    • Vous pouvez aussi utiliser la prop style pour assigner des styles inline.
    • Vous ne pouvez pas utiliser styled-jsx car il est limité au composant courant (sauf si vous marquez le style comme global).
  • Lors de l'utilisation de fill, l'élément parent doit avoir position: relative
    • Ceci est nécessaire pour le rendu correct de l'élément image dans ce mode de mise en page.
  • Lors de l'utilisation de fill, l'élément parent doit avoir display: block
    • C'est la valeur par défaut pour les éléments <div> mais doit être spécifiée autrement.

Exemples

Responsive

Image responsive remplissant la largeur et la hauteur de son conteneur parent
import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Responsive() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      <Image
        alt="Montagnes"
        // L'import d'une image définira
        // automatiquement la largeur et la hauteur
        src={mountains}
        sizes="100vw"
        // Faire en sorte que l'image s'affiche en pleine largeur
        style={{
          width: '100%',
          height: 'auto',
        }}
      />
    </div>
  )
}

Remplir le conteneur

Grille d'images remplissant la largeur du conteneur parent
import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Fill() {
  return (
    <div
      style={{
        display: 'grid',
        gridGap: '8px',
        gridTemplateColumns: 'repeat(auto-fit, minmax(400px, auto))',
      }}
    >
      <div style={{ position: 'relative', height: '400px' }}>
        <Image
          alt="Montagnes"
          src={mountains}
          fill
          sizes="(min-width: 808px) 50vw, 100vw"
          style={{
            objectFit: 'cover', // cover, contain, none
          }}
        />
      </div>
      {/* Et plus d'images dans la grille... */}
    </div>
  )
}

Image de fond

Image de fond prenant toute la largeur et hauteur de la page
import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Background() {
  return (
    <Image
      alt="Montagnes"
      src={mountains}
      placeholder="blur"
      quality={100}
      fill
      sizes="100vw"
      style={{
        objectFit: 'cover',
      }}
    />
  )
}

Pour des exemples du composant Image utilisé avec différents styles, voir la Démo du composant Image.

Autres propriétés

Voir toutes les propriétés disponibles pour le composant next/image.

Configuration

Le composant next/image et l'API d'optimisation d'images de Next.js peuvent être configurés dans le fichier next.config.js. Ces configurations permettent d'activer les images distantes, définir des points de rupture d'image personnalisés, modifier le comportement de cache et plus encore.

Lire la documentation complète sur la configuration des images pour plus d'informations.