Server Components : la norme, plus l'exception
Next.js 15 enterre le débat : un composant est serveur par défaut. Le marqueur `"use client"` devient l'exception documentée, et c'est une victoire nette pour la performance et la maintenabilité.
Concrètement : 80 % d'une app marketing typique peut rester en RSC. Les îlots clients se limitent aux composants manipulant état, effets, événements, APIs navigateur ou Framer Motion. Sur la base de code de VALRY LABS, cela représente moins de 15 % des composants.
Le piège classique : faire transiter des données non-sérialisables (Date, Map, fonctions) entre un Server et un Client Component. La règle stricte — ne passer que des types JSON-sérialisables ou des Server Actions — évite les surprises.
React 19 : actions, useActionState, useFormStatus
L'API Actions de React 19 unifie mutations et soumissions de formulaires. Une Server Action devient une fonction async typée, branchable directement sur `<form action={myAction}>`. Plus besoin de `onSubmit` + `fetch` côté client.
`useFormStatus` à l'intérieur du bouton submit expose `pending` sans prop drilling. `useActionState` sépare l'état succès/erreur du résultat. Le code de formulaire type passe de 60 lignes à 25.
Attention au piège UX : tant que l'action n'a pas terminé, l'utilisateur peut re-cliquer. Désactivez le bouton via `pending`, et gérez l'idempotence côté serveur (clé unique par soumission).
Partial Prerendering (PPR) : le graal SSR+SSG
PPR fusionne le meilleur du statique et du dynamique : une page peut être partiellement pré-rendue (shell statique) avec des morceaux dynamiques streamés en différé. Le LCP est servi immédiatement depuis le CDN, les données utilisateur arrivent ensuite.
Concrètement : marquez vos layouts/pages avec `experimental_ppr = true`, et Next.js statically prerender tout ce qui peut l'être, en laissant des trous (`<Suspense>`) pour les parties dynamiques.
En production sur VALRY LABS : la page d'accueil descend en LCP 0,6 s (de 1,1 s) sans sacrifier les données dynamiques (stats, testimonials, derniers articles). C'est la feature la plus impactante de la 15.
Caching : la grande clarification
Next.js 15 a supprimé le cache par défaut sur `fetch`. C'est la décision la plus saine du framework depuis 3 ans : trop d'équipes se sont fait piéger par des données stale en dev.
En contrepartie, vous devez être explicite : `fetch(url, { cache: 'force-cache' })` pour ISR, `next: { revalidate: 3600 }` pour un TTL, ou `cache: 'no-store'` pour dynamique strict.
Notre convention : toute route marketing utilise `export const revalidate = 3600` au niveau de la page, et toute route utilisateur-auth s'appuie sur le dynamic par défaut. Pas de surprises.
Migration 14 → 15 : le checklist
1. Mettre à jour `next`, `react`, `react-dom` en 15.x / 19.x. Faire tourner `codemod` officiel : `npx @next/codemod@latest upgrade`.
2. Vérifier les usages de `cookies()`, `headers()`, `params` qui sont désormais async (retournent une Promise). Le codemod les wrap automatiquement en `await`.
3. Auditer les `runtime = 'edge'` : certaines routes peuvent rester Node.js runtime, plus flexible. Edge reste pertinent pour les middlewares et les routes géo-distribuées.
4. Lancer le build en CI, corriger les erreurs de typage (React 19 resserre plusieurs types), et comparer le First Load JS avant/après — la 15 réduit souvent le bundle de 5-10 %.
5. Déployer progressivement (flags) sur la base traffic utilisateur, surveiller Sentry et les CWV pendant 7 jours.