Next.js 16 : Turbopack, Cache Components et proxy, ce qui change vraiment pour votre SaaS
Next.js 16 est sorti le 22 octobre 2025, et la version stable la plus récente au moment où j'écris ces lignes est la 16.4.x. Un an après, la question n'est plus de savoir si la migration en vaut la peine, mais quand elle va vous tomber dessus — parce que votre version actuelle vieillit et que vos dépendances finissent par l'exiger. Cet article fait le tour de ce qui change réellement, avec le code avant/après, et une checklist pour migrer un projet en production sans casser ce qui marche déjà.
Deux précisions honnêtes avant de commencer. D'abord, les chiffres de performance que je cite sont ceux annoncés par l'équipe : mesurez sur votre projet, les résultats varient fortement selon la taille du code et le nombre de routes. Ensuite, si vous lisez cet article après une nouvelle version mineure, vérifiez la documentation officielle — plusieurs options ont bougé de version mineure en version mineure. Le lien est en bas de page.
Ce qu'il faut retenir en une minute
- Turbopack est le bundler par défaut pour
next devetnext build. Le flag--turbopackest devenu inutile ;--webpackpermet de revenir en arrière. - Cache Components remplace PPR,
useCacheetdynamicIOpar un seul flag :cacheComponents: true. - Les APIs de requête sont 100 % asynchrones. L'échappatoire de compatibilité de Next.js 15 est supprimée :
cookies(),headers(),draftMode(),paramsetsearchParamsretournent des Promesses. middleware.tsdevientproxy.tset tourne en Node.js, pas en Edge.- React 19.2 et React Compiler sont inclus. Le compilateur reste opt-in.
- Plancher relevé : Node.js 20.9+, TypeScript 5.1+, navigateurs Chrome/Edge/Firefox 111+, Safari 16.4+.
Turbopack par défaut : ce qui change concrètement
C'est le changement le plus visible, et le plus simple. Avant, il fallait ajouter un flag pour en profiter ; maintenant, il faut un flag pour s'en passer. Si votre projet n'a pas de configuration webpack personnalisée, vous n'avez rien à faire : le script de build fonctionne tel quel.
// package.json — avant (Next.js 15)
{
"scripts": {
"dev": "next dev --turbopack",
"build": "next build --turbopack"
}
}
// package.json — après (Next.js 16) : les flags ne servent plus à rien
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}Le piège de la configuration webpack
Si votre projet déclare une fonction webpack dans next.config.js, le build échoue volontairement. Next.js préfère refuser de compiler plutôt que d'exécuter silencieusement une config que le nouveau bundler ignorerait. Trois issues possibles :
- Basculer sur Turbopack : la configuration se déclare à la racine de
next.configsous la cléturbopack, plus dansexperimental. - Continuer avec webpack :
next build --webpack. - Découvrir une config que vous n'avez pas écrite : si le build échoue sans que vous ayez déclaré de fonction webpack, c'est qu'un plugin en ajoute une. Regardez vos dépendances.
Deux détails de migration Turbopack à connaître. Le préfixe tilde des imports Sass (@import '~bootstrap/…') n'est plus supporté : il faut écrire le chemin direct. Et si votre code client importe un module Node (fs, par exemple), Turbopack propose turbopack.resolveAlias pour charger un module vide côté navigateur — mais la bonne réponse reste de ne pas importer un module Node côté client.
Cache Components : un seul flag pour le caching
Next.js 15 a fait entrer le rendu partiel (PPR) et des APIs de cache expérimentales dans les projets. Next.js 16 range tout ça sous une seule bannière : Cache Components. Quand on active le flag, le modèle de rendu devient PPR par défaut, et le compilateur met en cache ce qui peut l'être.
// next.config.js — Next.js 16
/** @type {import('next').NextConfig} */
const nextConfig = {
cacheComponents: true,
}
module.exports = nextConfigPoint important, et c'est là que beaucoup de migrations se corsent : activer ce flag n'est pas un simple renommage. Si vous l'activez sur un projet qui lit des données non mises en cache en dehors d'un <Suspense>, la construction échoue. Il faut adopter le modèle : entourer les lectures dynamiques, déclarer ce qui est mis en cache, et gérer l'expiration. Si vous n'utilisiez ni PPR ni dynamicIO, ne l'activez pas « pour faire la migration » : supprimez plutôt les flags expérimentaux devenus inutiles.
Les APIs de requête sont devenues asynchrones
Next.js 15 avait introduit cette rupture avec une période de tolérance. En 16, la tolérance est terminée. Toute lecture de la requête est une Promesse. Les cas concernés :
cookies(),headers(),draftMode()depuisnext/headersparamsdanslayout.js,page.js,route.js,default.js, et les fichiers de génération d'imagessearchParamsdanspage.js
// Avant (Next.js 14/15)
const store = await cookies()
const theme = store.get('theme')?.value
// Après (Next.js 16)
const store = await cookies()
const theme = (await store).get('theme')?.valueDeux autres endroits méritent votre attention. D'abord les paramètres asynchrones des images générées : la fonction qui produit un opengraph-image, twitter-image, icon ou apple-icon reçoit désormais params et id sous forme de Promesses, alors que generateImageMetadata continue de recevoir params de façon synchrone. Ensuite, si vous utilisez generateSitemaps, le paramètre id de votre fonction sitemap est aussi une Promesse.
middleware.ts devient proxy.ts
Le fichier change de nom et de fonction exportée. middleware est toujours reconnu en 16 — il est déprécié, pas supprimé — mais le nom proxy est la convention cible.
// Avant — src/middleware.ts
import { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// logique
}
// Après — src/proxy.ts
import { NextRequest } from 'next/server'
export function proxy(request: NextRequest) {
// logique
}La subtilité à ne pas rater : le runtime Edge n'est pas disponible dans proxy. C'est Node.js, et ce n'est pas configurable. Si votre middleware dépend d'API Edge — ou si vous le gardez volontairement léger pour un démarrage froid minimal — restez sur middleware.ts. La migration n'est donc pas automatique : c'est une décision, pas une formalité. Les options de configuration qui portaient le nom « middleware » ont été renommées en conséquence, par exemple skipMiddlewareUrlNormalize devient skipProxyUrlNormalize.
Ce qui est supprimé, et par quoi le remplacer
- AMP : toutes les APIs et la clé de configuration
ampdisparaissent. Les bénéfices de performance passent désormais par les optimisations intégrées et les standards du web. next lint: la commande est retirée, et le build ne lance plus le lint. Il faut appeler ESLint directement.serverRuntimeConfig/publicRuntimeConfig: remplacés par les variables d'environnement. Pour une valeur serveur, lisezprocess.envcôté serveur ; pour une valeur exposée au client, préfixezNEXT_PUBLIC_.- La clé
eslintde la config Next : retirée, elle aussi. experimental.dynamicIOetexperimental.useCache: supprimés, à remplacer parcacheComponentsou à supprimer selon votre usage.next/legacy/imageetimages.domains: dépréciés au profit denext/imageetimages.remotePatterns.
next/image : six changements de comportement
Si votre site utilise beaucoup d'images, c'est la section qui peut vous surprendre après coup. Aucun de ces changements n'est dramatique, mais ils peuvent modifier le rendu ou échouer silencieusement.
- Chaînes de requête sur les images locales :
/photo.jpg?v=2en local exige désormaisimages.localPatterns.search, sinon l'optimisation renvoie une erreur. minimumCacheTTLpasse de 60 secondes à 4 heures par défaut. Si vous tenez à l'ancien comportement, le déclarer explicitement.imageSizes: la valeur16sort du défaut. À rajouter si vous en avez besoin.qualities: le défaut devient[75]. Une qualité demandée hors de la liste est ramenée à la valeur la plus proche, et les requêtes/_next/imageavec unqnon supporté renvoient une erreur 400.- Adresses IP locales : l'optimisation des images servies depuis une IP privée est bloquée par défaut, pour des raisons de sécurité. À réactiver uniquement si vous savez ce que vous faites.
maximumRedirects: plafonné à 3 au lieu d'être illimité.
Les APIs de cache évoluent
revalidateTag exige désormais un second argument : un profil cacheLife. La forme à un seul argument est dépréciée et produit une erreur TypeScript.
// Avant
revalidateTag('posts')
// Après
revalidateTag('posts', 'max')Deux APIs arrivent en 16. updateTag, réservée aux Server Actions, expire et rafraîchit dans la même requête : l'utilisateur voit son changement immédiatement, sans donnée obsolète transitoire. C'est le bon outil pour un formulaire ou un réglage de compte. revalidateTag reste le bon choix pour du contenu où un court délai est acceptable — articles de blog, catalogue, documentation.
Dernière nouveauté : cacheLife et cacheTag sont stables, le préfixe unstable_ n'est plus nécessaire, et refresh() permet de rafraîchir le routeur client depuis une Server Action.
React 19.2 et React Compiler
L'App Router de Next.js 16 s'appuie sur React 19.2. Au menu : les View Transitions pour animer les éléments qui changent pendant une transition ou une navigation, useEffectEvent pour extraire d'une Effect une logique non réactive, et Activity pour masquer une interface tout en conservant son état.
React Compiler est stable, mais pas activé par défaut : l'équipe continue de recueillir des données de performance de build. Pour l'activer, il faut la clé reactCompiler dans la configuration et le plugin Babel. Attendez-vous à des temps de compilation plus longs, en développement comme en build.
Trois pièges supplémentaires avant de migrer
- Routes parallèles : chaque slot
@modaldoit déclarer undefault.js. Sans lui, le build échoue. Créez un fichier qui appellenotFound()ou qui retournenull. - Comportement de défilement : Next.js ne neutralise plus votre
scroll-behavior: smoothpendant les navigations. Si vous teniez à l'ancien comportement, ajoutezdata-scroll-behavior="smooth"sur l'élément<html>. - Métriques de build : la taille du bundle et le First Load JS ne sont plus affichés dans la sortie de
next build. Mesurez avec Lighthouse ou un outil d'analyse orienté Core Web Vitals.
Checklist de migration, dans l'ordre
L'ordre compte plus que la vitesse. Voici la séquence qui limite les allers-retours.
Avant de toucher au code
- Vérifiez le plancher : Node.js 20.9+, TypeScript 5.1+, et que vos navigateurs cibles sont dans la liste supportée.
- Sauvegardez l'état actuel : un build qui passe et des tests verts avant migration valent mieux qu'une migration aveugle.
- Inventoriez : une config webpack ? des
middleware.ts? desnext/imageavec chaîne de requête locale ? des flags expérimentaux ?
Pendant la migration
- Faites monter Next.js, React et React DOM, puis
@types/reactet@types/react-dom. - Lancez le codemod
upgrade: il met à jour la config Turbopack, retire le préfixeunstable_, et fait passermiddlewareenproxy. - Si votre code lit encore des APIs de requête de façon synchrone, lancez le codemod dédié
next-async-request-api. Il ne tourne pas tout seul. - Décidez de
cacheComponentsen connaissance de cause, pas par réflexe. - Mettez à jour
revalidateTaget vos appelsnext/image.
Après la migration
- Un build vert ne suffit pas. Vérifiez le comportement à l'exécution : routes, redirections, images, génération d'images OG, sitemaps.
- Testez les requêtes
/_next/imagedirectement, et rechargez les routes en navigation directe — c'est là que les slots parallèles sansdefault.jsse trahissent. - Ne remettez pas le lint dans le build : il ne s'y exécute plus, il faut l'appeler séparément.
Notre position sur la version à choisir
Nous maintenons plusieurs applications Next.js en production, et notre règle est simple : on ne migre pas un projet en production le jour de la sortie d'une majeure. On attend la première ou la deuxième version mineure, le temps que les codemods se stabilisent et que les retours d'expérience remontent. Pour un nouveau projet, en revanche, il n'y a aucune raison de partir sur une version antérieure : Turbopack par défaut et les outils de diagnostic valent le détour dès le premier commit.
Si vous partez de zéro ou si vous voulez éviter de porter une migration seule, nos templates SaaS sont livrés sur une base récente, avec l'authentification, la facturation et l'intégration IA déjà câblées. Voir les offres.
Conclusion
Next.js 16 n'est pas une révolution de paradigme : c'est une consolidation. Turbopack devient la norme, le caching devient explicite avec un seul flag, et les APIs de requête cessent de tolérer l'asynchrone optionnel. La migration se passe bien tant qu'on ne la traite pas comme un simple npm install : l'inventaire préalable des points de rupture — config webpack, middleware, images, APIs de cache — fait toute la différence.
Le coût réel d'une migration se mesure en heures d'inventaire, pas en heures de code. Une fois ces points vérifiés, la majeure partie du travail est mécanique.
Sources de cet article : le guide officiel de mise à niveau vers Next.js 16 et la documentation proxy. Les dates et numéros de version cités correspondent à l'état de la documentation au moment de la rédaction ; vérifiez la version installée chez vous avant de migrer.