Introduction/Guides/Redirections

Comment gérer les redirections dans Next.js

Il existe plusieurs façons de gérer les redirections dans Next.js. Cette page présente chaque option disponible, leurs cas d'utilisation et comment gérer un grand nombre de redirections.

APIObjectifEmplacementCode de statut
redirectRediriger l'utilisateur après une mutation ou un événementComposants Serveur, Actions Serveur, Gestionnaires de Route307 (Temporaire) ou 303 (Action Serveur)
permanentRedirectRediriger l'utilisateur après une mutation ou un événementComposants Serveur, Actions Serveur, Gestionnaires de Route308 (Permanent)
useRouterEffectuer une navigation côté clientGestionnaires d'événements dans les Composants ClientN/A
redirects dans next.config.jsRediriger une requête entrante basée sur un cheminFichier next.config.js307 (Temporaire) ou 308 (Permanent)
NextResponse.redirectRediriger une requête entrante basée sur une conditionMiddlewareQuelconque

Fonction redirect

La fonction redirect permet de rediriger l'utilisateur vers une autre URL. Vous pouvez appeler redirect dans les Composants Serveur, les Gestionnaires de Route et les Actions Serveur.

redirect est souvent utilisée après une mutation ou un événement. Par exemple, pour créer un article :

'use server'

import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'

export async function createPost(id: string) {
  try {
    // Appeler la base de données
  } catch (error) {
    // Gérer les erreurs
  }

  revalidatePath('/posts') // Mettre à jour les articles en cache
  redirect(`/post/${id}`) // Naviguer vers la page du nouvel article
}

Bon à savoir :

  • redirect retourne un code de statut 307 (Redirection Temporaire) par défaut. Lorsqu'elle est utilisée dans une Action Serveur, elle retourne un 303 (Voir Autre), couramment utilisé pour rediriger vers une page de succès après une requête POST.
  • redirect lance une erreur en interne et doit donc être appelée en dehors des blocs try/catch.
  • redirect peut être appelée dans les Composants Client pendant le processus de rendu mais pas dans les gestionnaires d'événements. Utilisez plutôt le hook useRouter.
  • redirect accepte également les URL absolues et peut être utilisée pour rediriger vers des liens externes.
  • Si vous souhaitez rediriger avant le processus de rendu, utilisez next.config.js ou Middleware.

Consultez la référence API de redirect pour plus d'informations.

Fonction permanentRedirect

La fonction permanentRedirect permet de rediriger permanentement l'utilisateur vers une autre URL. Vous pouvez appeler permanentRedirect dans les Composants Serveur, les Gestionnaires de Route et les Actions Serveur.

permanentRedirect est souvent utilisée après une mutation ou un événement qui change l'URL canonique d'une entité, comme la mise à jour de l'URL de profil d'un utilisateur après qu'il ait changé son nom d'utilisateur :

'use server'

import { permanentRedirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'

export async function updateUsername(username: string, formData: FormData) {
  try {
    // Appeler la base de données
  } catch (error) {
    // Gérer les erreurs
  }

  revalidateTag('username') // Mettre à jour toutes les références au nom d'utilisateur
  permanentRedirect(`/profile/${username}`) // Naviguer vers le nouveau profil utilisateur
}

Bon à savoir :

  • permanentRedirect retourne un code de statut 308 (Redirection Permanente) par défaut.
  • permanentRedirect accepte également les URL absolues et peut être utilisée pour rediriger vers des liens externes.
  • Si vous souhaitez rediriger avant le processus de rendu, utilisez next.config.js ou Middleware.

Consultez la référence API de permanentRedirect pour plus d'informations.

Hook useRouter()

Si vous devez rediriger dans un gestionnaire d'événements d'un Composant Client, vous pouvez utiliser la méthode push du hook useRouter. Par exemple :

'use client'

import { useRouter } from 'next/navigation'

export default function Page() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}

Bon à savoir :

  • Si vous n'avez pas besoin de naviguer programmatiquement un utilisateur, utilisez plutôt un composant <Link>.

Consultez la référence API de useRouter pour plus d'informations.

redirects dans next.config.js

L'option redirects dans le fichier next.config.js permet de rediriger un chemin de requête entrant vers une destination différente. C'est utile lorsque vous changez la structure d'URL des pages ou avez une liste de redirections connues à l'avance.

redirects prend en charge la correspondance de chemin, d'en-tête, de cookie et de requête, offrant la flexibilité de rediriger les utilisateurs en fonction d'une requête entrante.

Pour utiliser redirects, ajoutez l'option à votre fichier next.config.js :

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  async redirects() {
    return [
      // Redirection basique
      {
        source: '/about',
        destination: '/',
        permanent: true,
      },
      // Correspondance de chemin avec wildcard
      {
        source: '/blog/:slug',
        destination: '/news/:slug',
        permanent: true,
      },
    ]
  },
}

export default nextConfig

Consultez la référence API de redirects pour plus d'informations.

Bon à savoir :

  • redirects peut retourner un code de statut 307 (Redirection Temporaire) ou 308 (Redirection Permanente) avec l'option permanent.
  • redirects peut avoir une limite sur certaines plateformes. Par exemple, sur Vercel, la limite est de 1 024 redirections. Pour gérer un grand nombre de redirections (1000+), envisagez une solution personnalisée avec Middleware. Voir gérer les redirections à grande échelle pour plus d'informations.
  • redirects s'exécute avant le Middleware.

NextResponse.redirect dans Middleware

Le Middleware permet d'exécuter du code avant qu'une requête soit complétée. Ensuite, en fonction de la requête entrante, redirigez vers une URL différente avec NextResponse.redirect. C'est utile pour rediriger les utilisateurs en fonction d'une condition (ex : authentification, gestion de session) ou pour gérer un grand nombre de redirections.

Par exemple, pour rediriger l'utilisateur vers une page /login s'il n'est pas authentifié :

import { NextResponse, NextRequest } from 'next/server'
import { authenticate } from 'auth-provider'

export function middleware(request: NextRequest) {
  const isAuthenticated = authenticate(request)

  // Si l'utilisateur est authentifié, continuer normalement
  if (isAuthenticated) {
    return NextResponse.next()
  }

  // Rediriger vers la page de login si non authentifié
  return NextResponse.redirect(new URL('/login', request.url))
}

export const config = {
  matcher: '/dashboard/:path*',
}

Bon à savoir :

  • Le Middleware s'exécute après redirects dans next.config.js et avant le rendu.

Consultez la documentation sur le Middleware pour plus d'informations.

Gérer les redirections à grande échelle (avancé)

Pour gérer un grand nombre de redirections (1000+), vous pouvez envisager une solution personnalisée avec Middleware. Cela permet de gérer les redirections programmatiquement sans avoir à redéployer votre application.

Pour ce faire, vous devrez considérer :

  1. Créer et stocker une carte de redirections.
  2. Optimiser les performances de recherche de données.

Exemple Next.js : Consultez notre exemple Middleware avec filtre de Bloom pour une implémentation des recommandations ci-dessous.

1. Créer et stocker une carte de redirections

Une carte de redirections est une liste de redirections que vous pouvez stocker dans une base de données (généralement un magasin clé-valeur) ou un fichier JSON.

Considérez la structure de données suivante :

{
  "/old": {
    "destination": "/new",
    "permanent": true
  },
  "/blog/post-old": {
    "destination": "/blog/post-new",
    "permanent": true
  }
}

Dans le Middleware, vous pouvez lire depuis une base de données comme Edge Config de Vercel ou Redis, et rediriger l'utilisateur en fonction de la requête entrante :

import { NextResponse, NextRequest } from 'next/server'
import { get } from '@vercel/edge-config'

type RedirectEntry = {
  destination: string
  permanent: boolean
}

export async function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname
  const redirectData = await get(pathname)

  if (redirectData && typeof redirectData === 'string') {
    const redirectEntry: RedirectEntry = JSON.parse(redirectData)
    const statusCode = redirectEntry.permanent ? 308 : 307
    return NextResponse.redirect(redirectEntry.destination, statusCode)
  }

  // Aucune redirection trouvée, continuer sans rediriger
  return NextResponse.next()
}

2. Optimisation des performances de recherche de données

Lire un grand ensemble de données pour chaque requête entrante peut être lent et coûteux. Il existe deux façons d'optimiser les performances de recherche de données :

  • Utiliser une base de données optimisée pour les lectures rapides
  • Utiliser une stratégie de recherche de données comme un filtre de Bloom (Bloom filter) pour vérifier efficacement si une redirection existe avant de lire le fichier ou la base de données de redirections plus volumineux.

En reprenant l'exemple précédent, vous pouvez importer un fichier de filtre de Bloom généré dans le Middleware, puis vérifier si le chemin de la requête entrante existe dans le filtre de Bloom.

Si c'est le cas, transférez la requête vers un Route Handler qui vérifiera le fichier réel et redirigera l'utilisateur vers l'URL appropriée. Cela évite d'importer un gros fichier de redirections dans le Middleware, ce qui peut ralentir chaque requête entrante.

import { NextResponse, NextRequest } from 'next/server'
import { ScalableBloomFilter } from 'bloom-filters'
import GeneratedBloomFilter from './redirects/bloom-filter.json'

type RedirectEntry = {
  destination: string
  permanent: boolean
}

// Initialiser le filtre de Bloom à partir d'un fichier JSON généré
const bloomFilter = ScalableBloomFilter.fromJSON(GeneratedBloomFilter as any)

export async function middleware(request: NextRequest) {
  // Obtenir le chemin de la requête entrante
  const pathname = request.nextUrl.pathname

  // Vérifier si le chemin est dans le filtre de Bloom
  if (bloomFilter.has(pathname)) {
    // Transférer le chemin vers le Route Handler
    const api = new URL(
      `/api/redirects?pathname=${encodeURIComponent(request.nextUrl.pathname)}`,
      request.nextUrl.origin
    )

    try {
      // Récupérer les données de redirection depuis le Route Handler
      const redirectData = await fetch(api)

      if (redirectData.ok) {
        const redirectEntry: RedirectEntry | undefined =
          await redirectData.json()

        if (redirectEntry) {
          // Déterminer le code de statut
          const statusCode = redirectEntry.permanent ? 308 : 307

          // Rediriger vers la destination
          return NextResponse.redirect(redirectEntry.destination, statusCode)
        }
      }
    } catch (error) {
      console.error(error)
    }
  }

  // Aucune redirection trouvée, continuer la requête sans rediriger
  return NextResponse.next()
}

Ensuite, dans le Route Handler :

import { NextRequest, NextResponse } from 'next/server'
import redirects from '@/app/redirects/redirects.json'

type RedirectEntry = {
  destination: string
  permanent: boolean
}

export function GET(request: NextRequest) {
  const pathname = request.nextUrl.searchParams.get('pathname')
  if (!pathname) {
    return new Response('Bad Request', { status: 400 })
  }

  // Obtenir l'entrée de redirection depuis le fichier redirects.json
  const redirect = (redirects as Record<string, RedirectEntry>)[pathname]

  // Gérer les faux positifs du filtre de Bloom
  if (!redirect) {
    return new Response('No redirect', { status: 400 })
  }

  // Retourner l'entrée de redirection
  return NextResponse.json(redirect)
}

Bon à savoir :

  • Pour générer un filtre de Bloom, vous pouvez utiliser une bibliothèque comme bloom-filters.
  • Vous devriez valider les requêtes faites à votre Route Handler pour prévenir les requêtes malveillantes.

On this page