Redirections
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.
API | Objectif | Où l'utiliser | Code de statut |
---|---|---|---|
redirect | Rediriger l'utilisateur après une mutation ou un événement | Composants Serveur, Actions Serveur, Gestionnaires de Route | 307 (Temporaire) ou 303 (Action Serveur) |
permanentRedirect | Rediriger définitivement l'utilisateur | Composants Serveur, Actions Serveur, Gestionnaires de Route | 308 (Permanent) |
useRouter | Effectuer une navigation côté client | Gestionnaires d'événements dans les Composants Client | N/A |
redirects dans next.config.js | Rediriger une requête entrante basée sur un chemin | Fichier next.config.js | 307 (Temporaire) ou 308 (Permanent) |
NextResponse.redirect | Rediriger une requête basée sur une condition | Middleware | Quelconque |
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
}
'use server'
import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'
export async function createPost(id) {
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 par défaut un code de statut 307 (Redirection Temporaire). Lorsqu'elle est utilisée dans une Action Serveur, elle retourne un 303 (Voir Ailleurs), 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 blocstry/catch
.redirect
peut être appelée dans les Composants Client pendant le rendu, mais pas dans les gestionnaires d'événements. Utilisez plutôt le hookuseRouter
.redirect
accepte également les URLs absolues et peut être utilisée pour rediriger vers des liens externes.- Pour 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 définitivement 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 du profil d'un utilisateur après un changement de nom :
'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
}
'use server'
import { permanentRedirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'
export async function updateUsername(username, 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 par défaut un code de statut 308 (Redirection Permanente).permanentRedirect
accepte également les URLs absolues et peut être utilisée pour rediriger vers des liens externes.- Pour 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()
Pour 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>
)
}
'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, 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 des URLs 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 une grande flexibilité pour rediriger les utilisateurs.
Pour utiliser redirects
, ajoutez l'option à votre fichier next.config.js
:
module.exports = {
async redirects() {
return [
// Redirection simple
{
source: '/about',
destination: '/',
permanent: true,
},
// Correspondance avec wildcard
{
source: '/blog/:slug',
destination: '/news/:slug',
permanent: true,
},
]
},
}
Consultez la référence API de redirects
pour plus d'informations.
Bon à savoir :
redirects
peut retourner un code 307 (Redirection Temporaire) ou 308 (Redirection Permanente) avec l'optionpermanent
.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. Vous pouvez alors rediriger vers une autre URL avec NextResponse.redirect
en fonction de la requête entrante. C'est utile pour rediriger les utilisateurs selon une condition (ex : authentification, gestion de session) ou pour gérer un grand nombre de redirections.
Par exemple, pour rediriger vers une page /login
si l'utilisateur 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 sinon
return NextResponse.redirect(new URL('/login', request.url))
}
export const config = {
matcher: '/dashboard/:path*',
}
import { NextResponse } from 'next/server'
import { authenticate } from 'auth-provider'
export function middleware(request) {
const isAuthenticated = authenticate(request)
// Si l'utilisateur est authentifié, continuer normalement
if (isAuthenticated) {
return NextResponse.next()
}
// Rediriger vers la page de login sinon
return NextResponse.redirect(new URL('/login', request.url))
}
export const config = {
matcher: '/dashboard/:path*',
}
Bon à savoir :
- Le Middleware s'exécute après
redirects
dansnext.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 créer une solution personnalisée avec Middleware. Cela permet de gérer les redirections programmatiquement sans avoir à redéployer l'application.
Pour cela, vous devrez :
- Créer et stocker une carte de redirections.
- Optimiser les performances de recherche des données.
Exemple Next.js : Voir notre exemple Middleware avec filtre 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 selon 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()
}
import { NextResponse } from 'next/server'
import { get } from '@vercel/edge-config'
export async function middleware(request) {
const pathname = request.nextUrl.pathname
const redirectData = await get(pathname)
if (redirectData) {
const 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, comme Vercel Edge Config ou Redis.
- 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 Gestionnaire de route (Route Handler) qui vérifiera le fichier réel et redirigera l'utilisateur vers l'URL appropriée. Cela évite d'importer un fichier de redirections volumineux 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 Gestionnaire de route
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 Gestionnaire de route
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()
}
import { NextResponse } from 'next/server'
import { ScalableBloomFilter } from 'bloom-filters'
import GeneratedBloomFilter from './redirects/bloom-filter.json'
// Initialiser le filtre de Bloom à partir d'un fichier JSON généré
const bloomFilter = ScalableBloomFilter.fromJSON(GeneratedBloomFilter)
export async function middleware(request) {
// 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 Gestionnaire de route
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 Gestionnaire de route
const redirectData = await fetch(api)
if (redirectData.ok) {
const redirectEntry = 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 Gestionnaire de route :
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)
}
import { NextResponse } from 'next/server'
import redirects from '@/app/redirects/redirects.json'
export function GET(request) {
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[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 envoyées à votre Gestionnaire de route pour prévenir les requêtes malveillantes.