Liaison et Navigation

Il existe quatre façons de naviguer entre les routes dans Next.js :

Cette page expliquera comment utiliser chacune de ces options, et approfondira le fonctionnement de la navigation.

<Link> est un composant intégré qui étend la balise HTML <a> pour fournir un préchargement et une navigation côté client entre les routes. C'est la méthode principale et recommandée pour naviguer entre les routes dans Next.js.

Vous pouvez l'utiliser en l'important depuis next/link, et en passant une prop href au composant :

import Link from 'next/link'

export default function Page() {
  return <Link href="/dashboard">Dashboard</Link>
}

Il existe d'autres props optionnelles que vous pouvez passer à <Link>. Consultez la référence API pour en savoir plus.

Hook useRouter()

Le hook useRouter vous permet de changer de route programmatiquement depuis des Composants Client.

'use client'

import { useRouter } from 'next/navigation'

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

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

Pour une liste complète des méthodes de useRouter, consultez la référence API.

Recommandation : Utilisez le composant <Link> pour naviguer entre les routes, sauf si vous avez une exigence spécifique nécessitant l'utilisation de useRouter.

Fonction redirect

Pour les Composants Serveur, utilisez la fonction redirect à la place.

import { redirect } from 'next/navigation'

async function fetchTeam(id: string) {
  const res = await fetch('https://...')
  if (!res.ok) return undefined
  return res.json()
}

export default async function Profile({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  if (!id) {
    redirect('/login')
  }

  const team = await fetchTeam(id)
  if (!team) {
    redirect('/join')
  }

  // ...
}

Bon à savoir :

  • redirect retourne par défaut un code d'état 307 (Redirection Temporaire). Lorsqu'il est utilisé dans une Action Serveur, il 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, donc il doit être appelé en dehors des blocs try/catch.
  • redirect peut être appelé dans les Composants Client pendant le processus de rendu, mais pas dans les gestionnaires d'événements. Vous pouvez utiliser le hook useRouter à la place.
  • redirect accepte également les URLs absolues et peut être utilisé 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.

Utilisation de l'API History native

Next.js vous permet d'utiliser les méthodes natives window.history.pushState et window.history.replaceState pour mettre à jour la pile d'historique du navigateur sans recharger la page.

Les appels pushState et replaceState s'intègrent au routeur Next.js, vous permettant de vous synchroniser avec usePathname et useSearchParams.

window.history.pushState

Utilisez-le pour ajouter une nouvelle entrée à la pile d'historique du navigateur. L'utilisateur peut naviguer vers l'état précédent. Par exemple, pour trier une liste de produits :

'use client'

import { useSearchParams } from 'next/navigation'

export default function SortProducts() {
  const searchParams = useSearchParams()

  function updateSorting(sortOrder: string) {
    const params = new URLSearchParams(searchParams.toString())
    params.set('sort', sortOrder)
    window.history.pushState(null, '', `?${params.toString()}`)
  }

  return (
    <>
      <button onClick={() => updateSorting('asc')}>Trier par ordre croissant</button>
      <button onClick={() => updateSorting('desc')}>Trier par ordre décroissant</button>
    </>
  )
}
'use client'

import { useSearchParams } from 'next/navigation'

export default function SortProducts() {
  const searchParams = useSearchParams()

  function updateSorting(sortOrder) {
    const params = new URLSearchParams(searchParams.toString())
    params.set('sort', sortOrder)
    window.history.pushState(null, '', `?${params.toString()}`)
  }

  return (
    <>
      <button onClick={() => updateSorting('asc')}>Trier par ordre croissant</button>
      <button onClick={() => updateSorting('desc')}>Trier par ordre décroissant</button>
    </>
  )
}

window.history.replaceState

Utilisez-le pour remplacer l'entrée actuelle dans la pile d'historique du navigateur. L'utilisateur ne peut pas naviguer vers l'état précédent. Par exemple, pour changer la locale de l'application :

'use client'

import { usePathname } from 'next/navigation'

export function LocaleSwitcher() {
  const pathname = usePathname()

  function switchLocale(locale: string) {
    // ex. '/en/about' ou '/fr/contact'
    const newPath = `/${locale}${pathname}`
    window.history.replaceState(null, '', newPath)
  }

  return (
    <>
      <button onClick={() => switchLocale('en')}>Anglais</button>
      <button onClick={() => switchLocale('fr')}>Français</button>
    </>
  )
}
'use client'

import { usePathname } from 'next/navigation'

export function LocaleSwitcher() {
  const pathname = usePathname()

  function switchLocale(locale) {
    // ex. '/en/about' ou '/fr/contact'
    const newPath = `/${locale}${pathname}`
    window.history.replaceState(null, '', newPath)
  }

  return (
    <>
      <button onClick={() => switchLocale('en')}>Anglais</button>
      <button onClick={() => switchLocale('fr')}>Français</button>
    </>
  )
}

Fonctionnement du Routage et de la Navigation

Le routeur App utilise une approche hybride pour le routage et la navigation. Sur le serveur, votre code d'application est automatiquement découpé en morceaux par segments de route. Et sur le client, Next.js précharge et met en cache les segments de route. Cela signifie que lorsqu'un utilisateur navigue vers une nouvelle route, le navigateur ne recharge pas la page, et seuls les segments de route qui changent sont re-rendus - améliorant ainsi l'expérience de navigation et les performances.

1. Découpage du Code (Code Splitting)

Le découpage du code vous permet de diviser votre code d'application en paquets plus petits à télécharger et exécuter par le navigateur. Cela réduit la quantité de données transférées et le temps d'exécution pour chaque requête, améliorant ainsi les performances.

Les Composants Serveur permettent à votre code d'application d'être automatiquement découpé par segments de route. Cela signifie que seul le code nécessaire pour la route actuelle est chargé lors de la navigation.

2. Préchargement (Prefetching)

Le préchargement est un moyen de charger une route en arrière-plan avant que l'utilisateur ne la visite.

Il existe deux façons de précharger les routes dans Next.js :

  • Composant <Link> : Les routes sont automatiquement préchargées lorsqu'elles deviennent visibles dans le viewport de l'utilisateur. Le préchargement se produit lors du premier chargement de la page ou lorsqu'elle apparaît à l'écran par défilement.
  • router.prefetch() : Le hook useRouter peut être utilisé pour précharger des routes programmatiquement.

Le comportement de préchargement par défaut de <Link> (c'est-à-dire lorsque la prop prefetch n'est pas spécifiée ou définie à null) diffère selon votre utilisation de loading.js. Seule la mise en page partagée, en descendant l'"arbre" des composants rendus jusqu'au premier fichier loading.js, est préchargée et mise en cache pour 30s. Cela réduit le coût de récupération d'une route dynamique entière, et signifie que vous pouvez afficher un état de chargement instantané pour un meilleur retour visuel aux utilisateurs.

Vous pouvez désactiver le préchargement en définissant la prop prefetch à false. Alternativement, vous pouvez précharger les données complètes de la page au-delà des limites de chargement en définissant la prop prefetch à true.

Consultez la référence API de <Link> pour plus d'informations.

Bon à savoir :

  • Le préchargement n'est pas activé en développement, seulement en production.

3. Mise en Cache (Caching)

Next.js a un cache côté client en mémoire appelé Cache du Routeur. Lorsque les utilisateurs naviguent dans l'application, la charge utile des Composants Serveur React des segments de route préchargés et des routes visitées est stockée dans le cache.

Cela signifie que lors de la navigation, le cache est réutilisé autant que possible, au lieu de faire une nouvelle requête au serveur - améliorant les performances en réduisant le nombre de requêtes et de données transférées.

Apprenez-en plus sur le fonctionnement du Cache du Routeur et comment le configurer.

4. Rendu Partiel (Partial Rendering)

Le rendu partiel signifie que seuls les segments de route qui changent lors de la navigation sont re-rendus côté client, et tous les segments partagés sont préservés.

Par exemple, lors de la navigation entre deux routes sœurs, /dashboard/settings et /dashboard/analytics, la page settings sera démontée, la page analytics sera montée avec un nouvel état, et la mise en page partagée dashboard sera préservée. Ce comportement est également présent entre deux routes sur le même segment dynamique, par exemple avec /blog/[slug]/page et la navigation de /blog/first vers /blog/second.

Fonctionnement du rendu partiel

Sans rendu partiel, chaque navigation entraînerait un re-rendu complet de la page côté client. Le rendu uniquement du segment qui change réduit la quantité de données transférées et le temps d'exécution, améliorant ainsi les performances.

5. Navigation Douce (Soft Navigation)

Les navigateurs effectuent une "navigation dure" lors de la navigation entre les pages. Le routeur App de Next.js permet une "navigation douce" entre les pages, garantissant que seuls les segments de route qui ont changé sont re-rendus (rendu partiel). Cela permet de préserver l'état React côté client pendant la navigation.

6. Navigation Arrière et Avant

Par défaut, Next.js maintiendra la position de défilement pour les navigations arrière et avant, et réutilisera les segments de route dans le Cache du Routeur.

7. Routage entre pages/ et app/

Lors d'une migration progressive de pages/ vers app/, le routeur Next.js gérera automatiquement la navigation dure entre les deux. Pour détecter les transitions de pages/ vers app/, il y a un filtre de routeur côté client qui utilise une vérification probabiliste des routes d'application, ce qui peut occasionnellement entraîner des faux positifs. Par défaut, ces occurrences devraient être très rares, car nous configurons la probabilité de faux positifs à 0,01%. Cette probabilité peut être personnalisée via l'option experimental.clientRouterFilterAllowedRate dans next.config.js. Il est important de noter que réduire le taux de faux positifs augmentera la taille du filtre généré dans le bundle client.

Alternativement, si vous préférez désactiver complètement cette gestion et gérer manuellement le routage entre pages/ et app/, vous pouvez définir experimental.clientRouterFilter à false dans next.config.js. Lorsque cette fonctionnalité est désactivée, les routes dynamiques dans pages qui chevauchent des routes d'application ne seront pas correctement naviguées par défaut.