Comment créer une exportation statique de votre application Next.js

Next.js permet de démarrer comme un site statique ou une application monopage (SPA), puis de passer ultérieurement à des fonctionnalités nécessitant un serveur.

Lors de l'exécution de next build, Next.js génère un fichier HTML par route. En décomposant une SPA stricte en fichiers HTML individuels, Next.js peut éviter de charger du code JavaScript inutile côté client, réduisant ainsi la taille du bundle et permettant des chargements de page plus rapides.

Puisque Next.js prend en charge cette exportation statique, elle peut être déployée et hébergée sur n'importe quel serveur web capable de servir des ressources statiques HTML/CSS/JS.

Configuration

Pour activer une exportation statique, modifiez le mode de sortie dans next.config.js :

next.config.js
/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  output: 'export',

  // Optionnel : Change les liens `/me` -> `/me/` et émet `/me.html` -> `/me/index.html`
  // trailingSlash: true,

  // Optionnel : Empêche la conversion automatique `/me` -> `/me/`, préserve `href`
  // skipTrailingSlashRedirect: true,

  // Optionnel : Change le répertoire de sortie `out` -> `dist`
  // distDir: 'dist',
}

module.exports = nextConfig

Après avoir exécuté next build, Next.js créera un dossier out contenant les ressources HTML/CSS/JS de votre application.

Fonctionnalités prises en charge

Le cœur de Next.js a été conçu pour prendre en charge les exportations statiques.

Composants serveur

Lorsque vous exécutez next build pour générer une exportation statique, les composants serveur utilisés dans le répertoire app s'exécuteront pendant la construction, similairement à la génération traditionnelle de sites statiques.

Le composant résultant sera rendu en HTML statique pour le chargement initial de la page et en charge utile statique pour la navigation client entre les routes. Aucune modification n'est nécessaire pour vos composants serveur lors de l'utilisation de l'exportation statique, sauf s'ils consomment des fonctions serveur dynamiques.

export default async function Page() {
  // Cette requête s'exécutera sur le serveur pendant `next build`
  const res = await fetch('https://api.example.com/...')
  const data = await res.json()

  return <main>...</main>
}

Composants client

Si vous souhaitez effectuer une récupération de données côté client, vous pouvez utiliser un composant client avec SWR pour mémoriser les requêtes.

'use client'

import useSWR from 'swr'

const fetcher = (url: string) => fetch(url).then((r) => r.json())

export default function Page() {
  const { data, error } = useSWR(
    `https://jsonplaceholder.typicode.com/posts/1`,
    fetcher
  )
  if (error) return 'Échec du chargement'
  if (!data) return 'Chargement...'

  return data.title
}

Comme les transitions de route se produisent côté client, cela se comporte comme une SPA traditionnelle. Par exemple, la route d'index suivante vous permet de naviguer vers différents articles côté client :

import Link from 'next/link'

export default function Page() {
  return (
    <>
      <h1>Page d'index</h1>
      <hr />
      <ul>
        <li>
          <Link href="/post/1">Article 1</Link>
        </li>
        <li>
          <Link href="/post/2">Article 2</Link>
        </li>
      </ul>
    </>
  )
}

Optimisation des images

L'optimisation des images via next/image peut être utilisée avec une exportation statique en définissant un chargeur d'image personnalisé dans next.config.js. Par exemple, vous pouvez optimiser les images avec un service comme Cloudinary :

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',
  images: {
    loader: 'custom',
    loaderFile: './my-loader.ts',
  },
}

module.exports = nextConfig

Ce chargeur personnalisé définira comment récupérer les images depuis une source distante. Par exemple, le chargeur suivant construira l'URL pour Cloudinary :

export default function cloudinaryLoader({
  src,
  width,
  quality,
}: {
  src: string
  width: number
  quality?: number
}) {
  const params = ['f_auto', 'c_limit', `w_${width}`, `q_${quality || 'auto'}`]
  return `https://res.cloudinary.com/demo/image/upload/${params.join(
    ','
  )}${src}`
}

Vous pouvez ensuite utiliser next/image dans votre application, en définissant des chemins relatifs vers l'image dans Cloudinary :

import Image from 'next/image'

export default function Page() {
  return <Image alt="turtles" src="/turtles.jpg" width={300} height={300} />
}

Gestionnaires de route

Les gestionnaires de route rendront une réponse statique lors de l'exécution de next build. Seul le verbe HTTP GET est pris en charge. Cela peut être utilisé pour générer des fichiers statiques HTML, JSON, TXT ou autres à partir de données mises en cache ou non. Par exemple :

export async function GET() {
  return Response.json({ name: 'Lee' })
}

Le fichier ci-dessus app/data.json/route.ts sera rendu en un fichier statique pendant next build, produisant data.json contenant { name: 'Lee' }.

Si vous avez besoin de lire des valeurs dynamiques depuis la requête entrante, vous ne pouvez pas utiliser une exportation statique.

API navigateur

Les composants client sont pré-rendus en HTML pendant next build. Comme les API Web comme window, localStorage et navigator ne sont pas disponibles sur le serveur, vous devez accéder à ces API uniquement lors de l'exécution dans le navigateur. Par exemple :

'use client';

import { useEffect } from 'react';

export default function ClientComponent() {
  useEffect(() => {
    // Vous avez maintenant accès à `window`
    console.log(window.innerHeight);
  }, [])

  return ...;
}

Fonctionnalités non prises en charge

Les fonctionnalités nécessitant un serveur Node.js, ou une logique dynamique qui ne peut pas être calculée pendant le processus de construction, ne sont pas prises en charge :

Toute tentative d'utilisation de ces fonctionnalités avec next dev entraînera une erreur, similaire à la définition de l'option dynamic à error dans la mise en page racine.

export const dynamic = 'error'

Déploiement

Avec une exportation statique, Next.js peut être déployé et hébergé sur n'importe quel serveur web capable de servir des ressources statiques HTML/CSS/JS.

Lors de l'exécution de next build, Next.js génère l'exportation statique dans le dossier out. Par exemple, supposons que vous ayez les routes suivantes :

  • /
  • /blog/[id]

Après avoir exécuté next build, Next.js générera les fichiers suivants :

  • /out/index.html
  • /out/404.html
  • /out/blog/post-1.html
  • /out/blog/post-2.html

Si vous utilisez un hôte statique comme Nginx, vous pouvez configurer des réécritures depuis les requêtes entrantes vers les fichiers corrects :

nginx.conf
server {
  listen 80;
  server_name acme.com;

  root /var/www/out;

  location / {
      try_files $uri $uri.html $uri/ =404;
  }

  # Ceci est nécessaire lorsque `trailingSlash: false`.
  # Vous pouvez omettre ceci lorsque `trailingSlash: true`.
  location /blog/ {
      rewrite ^/blog/(.*)$ /blog/$1.html break;
  }

  error_page 404 /404.html;
  location = /404.html {
      internal;
  }
}

Historique des versions

VersionChangements
v14.0.0next export a été supprimé en faveur de "output": "export"
v13.4.0Le routeur d'application (stable) ajoute une meilleure prise en charge des exportations statiques, y compris l'utilisation des composants serveur React et des gestionnaires de route.
v13.3.0next export est déprécié et remplacé par "output": "export"

On this page