Next.js
Aide-mémoire Next.js 16 : 75 pratiques App Router pour la production
Un aide-mémoire pratique Next.js 16 avec 75 commandes, conventions de fichiers, pratiques Server Component, API de cache, champs SEO, contrôles de sécurité et conseils de déploiement.
Utilisez cette référence pendant le développement de projets App Router Next.js 16. Chaque entrée répond à une question précise, avec du code copiable lorsque la syntaxe compte.
Configuration du projet et commandes
Démarrez, examinez et mettez à niveau un projet Next.js 16 avec des commandes reproductibles. Les exemples utilisent npm, mais les concepts du framework sont indépendants du gestionnaire de paquets.
- 1
Créer un nouveau projet d'App Router
create-next-app configure Next.js, React, TypeScript et les outils choisis. Versionnez package-lock.json avec le projet.
npx create-next-app@latest my-app --ts --app --src-dir - 2
Utiliser la version Node.js de référence actuelle
Next.js 16 exige Node.js 20.9 ou une version ultérieure. Fixez une version prise en charge en développement local et en CI afin que les compilations ne dépendent pas des changements de version par défaut des runners.
- 3
Connaître les quatre scripts habituels
next dev lance le développement, next build crée le résultat de production, next start le sert et le linter configuré s’exécute séparément.
"scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "eslint ." } - 4
Installer de façon reproductible en CI
Utilisez npm ci lorsque package-lock.json est versionné. La commande rejette les écarts avec le fichier de verrouillage et installe l’arbre de dépendances résolu sans le réécrire.
npm ci && npm run build - 5
Utiliser Turbopack par défaut
Dans Next.js 16, next dev et next build utilisent tous deux Turbopack par défaut. Supprimez les anciennes options --turbo, sauf si un script doit prendre en charge une autre version.
- 6
Conserver temporairement une compilation webpack
Un projet doté d’une configuration webpack personnalisée peut désactiver explicitement Turbopack pendant la migration. Testez le résultat et les performances avant de changer l’outil de compilation de production.
next build --webpack - 7
Garder le code applicatif sous src
src/app et src/lib séparent le code applicatif de la configuration racine. Le répertoire public et les fichiers comme next.config.ts restent à la racine du projet.
- 8
Utiliser un alias d'importation
Un alias stable évite de longs chemins relatifs quand le code se déplace entre dossiers de routes. Gardez-le dans tsconfig.json ou jsconfig.json.
import { getUser } from "@/lib/data";
Pages, layouts et routage
App Router repose sur le système de fichiers. Ses conventions contrôlent les URL, l’interface partagée, les paramètres dynamiques et la navigation avancée.
- 9
Créer une page
Un fichier page.tsx rend la route de son dossier accessible publiquement. Son export par défaut fournit l’interface de cette URL.
export default function Page() { return <h1>About</h1>; } - 10
Créer le layout racine obligatoire
app/layout.tsx enveloppe chaque route et doit rendre html et body. Placez-y le CSS global, la langue, les providers du site et les métadonnées par défaut.
- 11
Imbriquer les layouts par segment de route
Un layout dans app/dashboard enveloppe la page du tableau de bord et tous ses descendants. Les layouts persistent pendant la navigation côté client dans leur sous-arbre.
- 12
Grouper les routes sans changer l’URL
Les parenthèses créent un groupe de routes. app/(marketing)/pricing/page.tsx reste associé à /pricing.
app/(marketing)/pricing/page.tsx - 13
Créer un segment dynamique
Les crochets capturent un segment d’URL. Dans Next.js 16, attendez params avant de lire la valeur.
export default async function Page({ params }) { const { slug } = await params; return <h1>{slug}</h1>; } - 14
Capturer plusieurs segments
[...parts] est un segment catch-all obligatoire ; [[...parts]] est facultatif. Utilisez-les pour une documentation hiérarchique ou d’autres chemins dont la profondeur dépend des données.
- 15
Prégénérer les chemins dynamiques connus
generateStaticParams renvoie les objets de paramètres des routes que Next.js doit générer à la compilation.
export function generateStaticParams() { return posts.map((post) => ({ slug: post.slug })); } - 16
Rejeter les chemins dynamiques inconnus
Définissez dynamicParams à false si seules les valeurs renvoyées par generateStaticParams doivent être résolues. Les autres valeurs renvoient 404.
export const dynamicParams = false; - 17
Afficher une ressource manquante
Appelez notFound lorsque la route existe mais pas l’entité demandée. Next.js rend la limite not-found.tsx la plus proche.
if (!post) notFound(); - 18
Réinitialiser l’état avec un template
template.tsx ressemble à un layout, mais est remonté à la navigation. Utilisez-le pour réinitialiser l’état et les effets ; gardez les structures persistantes dans les layouts.
- 19
Afficher simultanément les emplacements de routes
Les dossiers comme @team et @analytics définissent des emplacements de routes parallèles transmis au layout parent. Fournissez des contenus par défaut default.tsx pour les emplacements sans correspondance lors d’une navigation directe.
- 20
Ouvrir une route dans une fenêtre modale
Les routes d’interception peuvent afficher une autre route dans le layout actuel pendant la navigation côté client, tout en conservant sa page complète pour l’actualisation et les liens partagés.
Server Components et Client Components
Les Server Components sont le choix par défaut d’App Router. Ajoutez du JavaScript navigateur uniquement aux composants qui exigent des interactions ou des API propres au navigateur.
- 21
Garder les pages côté serveur par défaut
Un Server Component peut attendre des données, utiliser des variables d’environnement privées et produire le rendu sans envoyer son code au navigateur.
- 22
Déclarer un Client Component
Placez la directive avant les imports. La limite côté client comprend ce module et le graphe de dépendances client qu’il importe.
"use client"; import { useState } from "react"; - 23
Utiliser les composants clients pour les interactions
L’état, les effets, les gestionnaires d’événement, les hooks personnalisés, window, localStorage et les autres API navigateur appartiennent aux Client Components.
- 24
Utiliser le serveur pour les opérations privées
Les requêtes de base de données, identifiants de services, grosses bibliothèques réservées au serveur et l’essentiel du rendu de contenu appartiennent aux Server Components ou modules server-only.
- 25
Transmettre des props sérialisables aux clients
Les chaînes, nombres, booléens, tableaux, objets simples et valeurs React prises en charge peuvent franchir la limite. Limitez les données transmises et n’envoyez pas les enregistrements privés complets.
- 26
Marquer les modules privés avec server-only
Cet import à effet de bord fait échouer un import client à la compilation, protégeant ainsi le code d’accès aux données d’un usage accidentel dans le navigateur.
import "server-only"; - 27
Descendre la limite côté client
Gardez la page et le layout rendus sur le serveur, puis isolez un champ de recherche, un menu, un sélecteur ou un graphique dans le plus petit Client Component utile.
- 28
Transmettre le rendu serveur via les enfants d’un composant client
Un Client Component peut recevoir un Server Component comme enfant ou autre prop. Le sous-arbre rendu sur le serveur reste ainsi hors du graphe des modules du client.
- 29
Placer les providers aussi bas que possible
Le contexte est indisponible dans les Server Components. Rendez un provider Client Component ciblé autour du seul sous-arbre qui le consomme, plutôt qu’autour de tout le document par défaut.
Récupération, streaming et cache
Choisissez délibérément la fraîcheur. Cache Components est facultatif dans Next.js 16 ; l’aide-mémoire indique les API qui exigent son activation.
- 30
Récupérer des données dans un Server Component asynchrone
Appelez une API, un ORM ou une base depuis le composant qui rend le résultat. Vous n’avez pas besoin d’un Route Handler interne uniquement pour appeler votre propre serveur.
export default async function Page() { const products = await getProducts(); return <ProductList products={products} />; } - 31
Lancer ensemble les tâches indépendantes
Promise.all évite une cascade de requêtes lorsque les deux opérations n’ont pas besoin du résultat l’une de l’autre.
const [user, projects] = await Promise.all([ getUser(), getProjects(), ]); - 32
Diffuser avec un fichier de chargement de route
loading.tsx enveloppe le segment dans une limite Suspense et fournit immédiatement un contenu d’attente pendant la navigation et le rendu à la requête.
- 33
Diffuser une zone lente en streaming
Placez Suspense autour du composant lent pour laisser le reste de la page s’afficher d’abord. Donnez au contenu d’attente des dimensions proches du résultat final.
<Suspense fallback={<ActivitySkeleton />}> <RecentActivity /> </Suspense> - 34
Mémoïser un passage de rendu
React cache peut dédupliquer les appels à une même fonction de données serveur avec les mêmes arguments pendant un rendu. Ce n’est pas un cache applicatif persistant.
import { cache } from "react"; export const getUser = cache(async (id) => db.user.findUnique({ where: { id } })); - 35
Activer Cache Components
Les API use cache de Next.js 16 exigent le paramètre cacheComponents. Migrez délibérément, car cela change le rendu et le cache.
const nextConfig = { cacheComponents: true }; export default nextConfig; - 36
Mettre en cache une fonction asynchrone
Avec Cache Components activé, placez use cache en tête d’une fonction asynchrone ou du corps d’un composant. Les arguments sérialisables deviennent une partie de la clé de cache.
export async function getProducts() { "use cache"; return db.product.findMany(); } - 37
Définir une durée de vie du cache
cacheLife accepte un profil nommé ou des durées personnalisées. Choisissez la durée selon le degré de péremption acceptable du contenu, pas par commodité.
"use cache"; cacheLife("hours"); - 38
Taguer les données en cache liées
cacheTag attribue à plusieurs entrées un tag d’invalidation commun, comme products ou post-42.
"use cache"; cacheTag("products"); - 39
Faire expirer un chemin
Appelez revalidatePath depuis une Server Function ou un Route Handler après un changement qui rend une page ou un layout périmé.
revalidatePath("/blog"); - 40
Revalider par tag
Utilisez revalidateTag si le contenu tagué peut suivre le comportement stale-while-revalidate. Choisissez un profil de cache adapté au besoin de fraîcheur.
- 41
Voir immédiatement sa propre écriture avec updateTag
Appelez updateTag dans une Server Action si son utilisateur doit voir immédiatement les données taguées à jour après la mutation.
await savePost(input); updateTag("posts");
Formulaires, mutations et Route Handlers
Les écritures nécessitent validation, autorisation, erreurs prévisibles et mise à jour explicite du cache. Les interfaces HTTP exigent aussi la sécurité habituelle des endpoints.
- 42
Déclarer une Server Action
Placez use server en tête d’une fonction asynchrone ou d’un module d’actions. Traitez les Server Actions exportées comme des endpoints de mutation appelables à distance.
"use server"; export async function createPost(formData: FormData) { // validate, authorize, mutate, invalidate } - 43
Relier une action à un formulaire
Un formulaire peut appeler une Server Action sans gestionnaire client personnalisé. Le comportement natif des formulaires du navigateur permet aussi une amélioration progressive.
<form action={createPost}>...</form> - 44
Valider FormData sur le serveur
Considérez les noms, identifiants, fichiers, champs cachés et validations client comme non fiables. Validez-les avec un schéma explicite avant l’écriture.
- 45
Renvoyer les erreurs de formulaire attendues
Utilisez un résultat sérialisable et useActionState pour les erreurs de validation ou métier que l’utilisateur peut corriger. Ne levez pas d’exception pour chaque résultat attendu.
- 46
Afficher l’état d’envoi du formulaire
useFormStatus lit l’état d’envoi du formulaire parent. Désactivez les envois répétés et donnez au bouton un libellé fidèle à l’état en cours.
- 47
Créer un Route Handler
route.ts exporte les fonctions des verbes HTTP et utilise les API Web Request et Response. Un fichier route.ts ne peut pas partager le même segment que page.tsx.
export async function GET() { return Response.json({ status: "ok" }); } - 48
Lire un paramètre dynamique de Route Handler
Les params du contexte de route sont asynchrones dans les versions actuelles de Next.js. Attendez-les avant d’interroger la ressource.
export async function GET(request, { params }) { const { id } = await params; return Response.json(await getItem(id)); } - 49
Rediriger après une mutation
Utilisez redirect pour une navigation temporaire après une création ou mise à jour réussie, et permanentRedirect uniquement si la ressource possède une nouvelle URL canonique durable.
redirect("/dashboard"); - 50
Permettre de nouvelles tentatives sans risque
Les webhooks et requêtes réseau peuvent arriver plusieurs fois. Enregistrez les identifiants d’événement du prestataire ou les clés d’idempotence avant de répéter paiements, e-mails ou autres effets de bord.
SEO, images, polices et scripts
Next.js peut générer les balises head et fichiers des robots depuis le code des routes. La page visible doit encore offrir un contenu précis et utile, avec une structure sémantique.
- 58
Définir les métadonnées statiques
Exportez les métadonnées depuis un layout ou une page Server Component si les valeurs ne dépendent pas des données de route.
export const metadata = { title: "Pricing", description: "Simple plans for growing teams.", }; - 59
Générer des métadonnées dynamiques
Utilisez generateMetadata pour les titres, descriptions, URL canoniques et images sociales propres à une entité. Réutilisez si possible la fonction d’accès aux données de la route.
- 60
Définir metadataBase une seule fois
metadataBase à la racine permet aux liens canoniques et aux champs d’images d’utiliser des chemins relatifs que Next.js résout en URL absolues.
metadataBase: new URL("https://example.com") - 61
Générer un sitemap
app/sitemap.ts renvoie les URL publiques et les champs facultatifs lastModified, changeFrequency et priority. Générez-le depuis le catalogue réel du contenu ; Google ignore changeFrequency et priority, donc gardez lastModified exact plutôt que de fabriquer de la fraîcheur.
- 62
Publier les règles robots
app/robots.ts renvoie les règles d’exploration et l’emplacement du sitemap. Ces règles sont des indications pour les robots, pas un contrôle d’accès aux routes privées.
- 63
Utiliser des images optimisées
next/image nécessite des dimensions intrinsèques ou un conteneur fill. Fournissez un texte alt exact et des tailles responsives ; réservez priority aux images critiques visibles avant défilement.
- 64
Charger les polices avec next/font
next/font héberge les fichiers de polices choisis et réduit les requêtes externes. Limitez les graisses et sous-ensembles aux styles réellement utilisés.
- 65
Planifier le chargement des scripts tiers
next/script contrôle le moment où le JavaScript externe se charge. Choisissez afterInteractive ou lazyOnload, sauf si l’intégration fait réellement partie du chemin critique.
Sécurité et configuration
Les limites du framework ne réduisent l’exposition accidentelle que si le code applicatif garde explicites les autorisations et la gestion des secrets.
- 66
Garder les secrets côté serveur
Les valeurs d’environnement restent réservées au serveur sauf si leur nom commence par NEXT_PUBLIC_. Tout ce qui porte ce préfixe doit être considéré comme visible dans le navigateur et fixé selon l’environnement de compilation.
- 67
Vérifier l’autorisation à chaque point d’entrée serveur
Vérifiez l’identité actuelle et ses permissions dans les Server Actions, Route Handlers et accès protégés aux données. Un bouton caché ou une redirection Proxy ne constitue pas une limite de sécurité.
- 68
Utiliser Proxy pour la logique de routage liée aux requêtes
Next.js 16 utilise proxy.ts pour les réécritures, redirections et contrôles optimistes avant qu’une requête atteigne une route. Gardez aussi les autorisations sécurisées près des données.
- 69
Utiliser des cookies de session sécurisés
Définissez les attributs HTTP-only, secure, same-site, path et d’expiration selon la conception des sessions. Renouvelez et invalidez les sessions via le système d’authentification.
- 70
Envoyer au navigateur uniquement les données nécessaires
Convertissez les enregistrements en DTO contenant uniquement les champs nécessaires à l’interface. Les API de marquage de données sensibles peuvent ajouter une défense en profondeur, sans remplacer une sélection rigoureuse des données renvoyées.
Production, débogage et déploiement
Les cinq derniers contrôles transforment le code du framework en site exploitable, avec des compilations reproductibles et des versions observables.
- 71
Exécuter les vérifications séparément
Next.js 16 n’utilise pas next build pour le lint. Faites du lint, de TypeScript, des tests et de la compilation de production des étapes CI distinctes.
npm run lint npx tsc --noEmit npm test npm run build - 72
Tester le serveur de production
Exécutez next build et next start localement ou dans un aperçu. Le développement peut masquer des problèmes d’import, de cache, d’environnement et de rendu propres à la production.
- 73
Lire le résumé de compilation des routes
Le résultat de next build identifie les routes prérendues et celles rendues à la requête. Examinez une route qui devient dynamique ou grossit de façon inattendue plutôt que de limiter la compilation à un statut réussi ou échoué.
- 74
Exposer un contrôle de santé fidèle à l’état réel
Renvoyez une petite réponse de succès uniquement si le processus est prêt à recevoir du trafic. Gardez les secrets et les détails des dépendances hors du corps public de la réponse.
export function GET() { return Response.json({ status: "ok" }); } - 75
Déployer le processus de production normal
Un déploiement serveur standard installe à partir du fichier de verrouillage, exécute next build, démarre avec next start, injecte les secrets d’exécution, vérifie la santé et ne promeut qu’une version opérationnelle.
build_cmd: npm ci && npm run build start_cmd: npm start runtime: name: node@24 port: 3000 health_path: /api/health