← retour Un terminal ambre brillant sur le bureau d'un développeur la nuit, une tasse de café vide à côté d'un clavier usé, une fenêtre striée de pluie en arrière-plan

Migrer vers Next.js 16 : mes notes réelles de migration

Il y a trois semaines, j'étais assis au bureau de Seahawk un jeudi après-midi, assez confiant que la mise à niveau de Next.js 15 vers 16 sur l'un de mes sites portfolio personnels prendrait quarante minutes maximum. Ça m'a pris le reste de la journée. Et honnêtement ? Le changelog ne vous prépare pas vraiment aux parties qui cassent réellement.

J'ai construit et déployé plus de 12 000 sites jusqu'à présent. Je ne dis pas ça pour frimer, je le dis parce que j'ai fait assez de ces migrations pour savoir quand le guide de mise à niveau officiel passe quelque chose sous silence. Next.js 16 en passe sous silence quelques éléments. Voici donc mes notes réelles, écrites de la façon dont j'aurais aimé que quelqu'un les écrive pour moi.

---

Pourquoi j'ai décidé de faire cette mise à niveau

Turbopack. C'est la réponse courte.

La réponse plus longue est que deux de mes sites étaient sur Next.js 14, l'un était déjà sur 15, et j'ai suivi l'évolution de Turbopack pendant environ dix-huit mois. La version 16 est la première version où Turbopack est activé par défaut pour next dev. Ce n'est pas un détail mineur. Sur un projet e-commerce de taille moyenne que j'ai fait pour un client dans la mode l'année dernière, les temps de démarrage à froid en développement étaient terribles, on parlait de 12 à 18 secondes au premier chargement. Si Turbopack réduit vraiment cela, la douleur de la migration en vaut la peine.

Spoiler : oui, ça la réduit. Sur le même type de projet, je vois des démarrages à froid de 3 à 4 secondes. C'est du concret.

Mais le chemin pour y arriver présente quelques aspérités.

---

La vraie commande de mise à niveau (et ce qu'il faut exécuter en premier)

Avant de toucher à quoi que ce soit, exécutez un audit complet de votre configuration actuelle. J'utilise npx @next/codemod@latest religieusement maintenant. Ça ne verra pas tout mais ça verra les renommages évidents et les appels d'API dépréciés. Exécutez-le, validez la sortie, puis augmentez votre package.json.

La mise à niveau elle-même :

  1. Mettez à jour next, react et react-dom vers leurs versions cibles dans package.json
  2. Exécutez npm install (ou pnpm install si vous êtes sensé, j'utilise pnpm depuis deux ans)
  3. Exécutez le codemod : npx @next/codemod@latest upgrade
  4. Démarrez next dev et lisez chaque avertissement avant de toucher un seul composant
  5. Corrigez les problèmes de configuration avant de corriger les problèmes de composants, l'ordre compte ici

L'étape du codemod est là où j'ai vu des gens se tromper. Ils la sautent, rencontrent trois erreurs distinctes, et passent une heure à chercher des choses qui auraient été corrigées automatiquement. Ne la sautez pas.

---

Les changements de next.config.js qui vous donneront du fil à retordre

C'était la première véritable surprise pour moi. L'API de configuration a changé plus que je ne l'attendais.

Le bloc `experimental` est plus épuré maintenant

Plusieurs flags qui ont vécu en experimental pendant un an ou deux ont soit été promus en stable (et déplacés au niveau supérieur) soit supprimés complètement. Les deux que j'ai personnellement rencontrés :

  • experimental.appDir, disparu. App Router est maintenant juste le défaut. Si vous avez cela dans votre config, ça va afficher un warning (et dans certaines configurations, une erreur franche).
  • experimental.serverComponentsExternalPackages, promu à serverExternalPackages au niveau supérieur de votre config.

C'est celui-ci qui m'a eu sur un site qui utilise Prisma. Le build échouait silencieusement sur le bundle serveur et j'ai probablement passé quarante minutes à fixer le mauvais fichier avant de le repérer. Vérifiez votre next.config.js de haut en bas avant de supposer qu'un composant est le coupable.

La config de Turbopack vit dans un nouvel endroit

Si vous aviez une custom Webpack config et vous basculez vers Turbopack (ce que vous allez faire, puisque c'est maintenant le défaut pour le dev), vous devez savoir que votre fonction webpack() dans next.config.js ne s'applique pas quand Turbopack tourne. Elle ne s'applique que pendant next build, qui utilise toujours Webpack.

C'est important si vous aviez un custom SVG handling (j'utilise SVGR sur la plupart de mes projets), des custom module aliases, ou n'importe quelle config de loader. Vous allez devoir répliquer tout ça dans le nouveau bloc de config turbopack. La documentation de configuration Turbopack de Next.js est en fait décente sur celui-ci, ça vaut le coup de lire avant de supposer que quelque chose est cassé.

---

Compatibilité React 19 : Le Piège Silencieux

Next.js 16 est livré avec React 19 comme sa peer dependency. Si vous mettez à jour depuis Next.js 14 (en sautant 15), vous sautez deux versions majeures de React à la fois. C'est là que ça devient épicé.

Le plus gros problème que j'ai rencontré était avec des anciennes librairies de composants tiers. J'avais un site client qui utilisait une librairie de table qui utilisait en interne ReactDOM.render(). React 19 a complètement supprimé cette API, elle était dépréciée depuis React 18 mais elle marchait encore. En 19, ça lance une erreur. Fort.

J'ai passé un mardi matin sur celui-ci. Le message d'erreur ne vous pointe pas immédiatement vers la librairie; il vous dit juste que ReactDOM.render n'est plus supporté. Lancez npm ls react pour voir quels packages dans votre arbre ont des déclarations de peer dependency React conflictuelles. Cette commande seule m'a sauvé probablement deux heures de devinage.

Quelques patterns qui valent le coup de connaître pour React 19 spécifiquement :

  • forwardRef n'est plus requis pour passer des refs; les refs sont maintenant une prop ordinaire. Les anciens composants utilisant forwardRef marchent toujours, mais vous allez voir des warnings de dépréciation.
  • use() est stable maintenant et genuinely utile pour les données async dans les client components. J'ai commencé à l'utiliser en préférence à useEffect + state pour les fetches simples.
  • Les Server Actions ont des exigences de type plus strictes. Si vous aviez quelque chose de faiblement typé dans vos signatures d'action, TypeScript le trouvera maintenant.

---

App Router : Ce Qui A Changé dans le Comportement de Caching

Celui-ci est subtil et il vous attrapera en production si vous n'y faites pas attention.

En arrière dans Next.js 14, fetch() à l'intérieur des Server Components était cachée agressivement par défaut. Vous deviez vous en désinscrire avec { cache: 'no-store' }. En Next.js 15 ils ont inversé ça (fetch est non-cachée par défaut), et Next.js 16 continue dans cette direction avec quelques contrôles plus explicites.

Si vous avez migré de 14 à 16 d'un seul coup (comme je l'ai fait avec un de mes sites), vos pages qui se reposaient sur l'ancien comportement de caching par défaut vont commencer à faire des fetches en direct à chaque requête. Pour certaines pages, c'est bien. Pour d'autres, ça va marteler votre API et détruire vos temps de réponse.

The fix is explicit: use export const revalidate = 3600 (or whatever interval makes sense) at the route segment level, or pass { next: { revalidate: 3600 } } directly in your fetch call. The Next.js caching documentation has a solid breakdown of what caches what and when.

J'ai audité chaque route de data-fetching sur le site affecté en utilisant un grep rapide pour fetch( et j'ai ajouté des déclarations de caching explicites. Ça a pris environ deux heures mais ça en valait la peine, les temps de réponse sont passés de ~800ms en moyenne à ~120ms après le fix.

---

Turbopack en Pratique : Le Bon et l'Ennuyant

Laissez-moi être direct avec vous : Turbopack est impressionnant. Les temps de démarrage à froid sont dramatiquement meilleurs. Le hot module replacement se sent presque instantané sur la plupart des changements. Pour le dev au quotidien c'est une amélioration qualité de vie significative.

Mais il y a des points rugueux.

Ce qui ne marche pas encore

À l'époque où j'ai fait ces migrations, une poignée de choses n'étaient toujours pas complètement supportées sous Turbopack pour le dev :

  • Certains chargeurs spécifiques à Webpack n'ont pas encore d'équivalent Turbopack. SVGR a nécessité un changement de configuration (la syntaxe des règles Turbopack est différente de celle de module.rules dans Webpack).
  • Les transformations Babel personnalisées. Turbopack utilise uniquement SWC. Si votre projet a un fichier .babelrc ou babel.config.js avec des plugins personnalisés, ils ne s'exécuteront pas. C'est une limitation connue et l'équipe Vercel est transparente à ce sujet dans sa documentation Turbopack.
  • Certaines combinaisons de plugins PostCSS se comportent de manière inattendue en développement. Je l'ai observé avec Tailwind v4 + une configuration PostCSS personnalisée, la solution a été d'épingler explicitement l'ordre des plugins PostCSS.

Le drapeau `--turbopack` n'est plus nécessaire

Puisque Turbopack est le défaut pour next dev dans la version 16, vous n'avez plus besoin du drapeau --turbopack. Si vous l'avez dans vos scripts package.json suite à des expériences avec la version 15, cela ne causera aucun problème, mais c'est redondant. Nettoyez vos scripts.

---

Mises à jour de la configuration TypeScript et ESLint

Deux choses de maintenance qui m'ont trompé.

Next.js 16 exige désormais TypeScript 5.x. Si vous êtes toujours sur TypeScript 4.x (certains anciens projets le sont), vous devez le mettre à niveau séparément. Exécutez npx tsc --version avant de commencer autre chose.

L'histoire de la configuration ESLint a également changé. Next.js 16 est livré avec le support d'ESLint 9, et ESLint 9 utilise un format de configuration plat (eslint.config.js) plutôt que l'ancien format .eslintrc. Si vous êtes toujours sur l'ancien format, Next.js reviendra gracieusement, mais vous verrez un avertissement. J'ai migré deux de mes projets vers la configuration plat du même coup. C'est honnêtement plus propre une fois qu'on surmonte les frictions initiales.

---

Ma Liste de Contrôle de Migration (Dans l'Ordre)

C'est ce que je remettrais à quiconque dans mon équipe effectuant cette mise à jour :

  1. Sauvegardez vos fichiers de configuration actuels et votre fichier lock avant de toucher à quoi que ce soit
  2. Vérifiez votre version de Node.js, Next.js 16 nécessite Node 18.18 ou supérieur
  3. Exécutez npx @next/codemod@latest upgrade sur la version actuelle d'abord
  4. Augmentez les versions next, react, react-dom dans package.json et installez
  5. Examinez next.config.js pour les drapeaux expérimentaux promus ou supprimés
  6. Exécutez npm ls react pour repérer les conflits de bibliothèques tierces
  7. Consultez votre base de code pour fetch( et auditez les déclarations de mise en cache
  8. Vérifiez la présence de fichiers .babelrc ou de chargeurs spécifiques à Webpack nécessitant des équivalents Turbopack
  9. Démarrez le dev, lisez tous les avertissements avant de modifier les composants
  10. Exécutez une compilation de production localement (next build) avant de déployer où que ce soit
  11. Déployez dans un environnement de test et effectuez un test de fumée manuel complet

Cette dernière étape semble évidente. Mais j'ai vu des gens sauter le test et pousser directement vers la production sur des mises à jour « mineures ». Un changement de comportement de mise en cache qui fait que votre page d'accueil accède à une API active à chaque demande n'est pas une petite chose.

---

FAQ

Next.js 16 est-il assez stable pour la production ?

Oui, pour la plupart des cas d'usage. Le changement Turbopack-for-dev est le plus important, et puisque les builds de production utilisent toujours Webpack, votre output déployé est moins affecté que votre expérience de développement. Les changements de comportement du cache sont la plus grande préoccupation en production, et ils sont simples à auditer si vous êtes méthodique.

Dois-je mettre à jour React à la version 19 en même temps ?

Techniquement, Next.js 16 supporte React 18 comme minimum, mais les nouvelles fonctionnalités (comme le hook use() stable et le changement ref-as-prop) nécessitent React 19. Si vous êtes sur un projet avec beaucoup de dépendances tierces, ça vaut le coup de vérifier la compatibilité avant de vous engager dans une mise à jour de React 19 en même temps. Le guide de mise à jour de React 19 vaut vraiment la peine d'être lu en même temps que la documentation de migration de Next.js.

Ma configuration Webpack personnalisée a disparu avec Turbopack. Que dois-je faire ?

Votre configuration Webpack s'exécute toujours lors de next build. En développement, vous devez reproduire les parties pertinentes en utilisant la clé turbopack dans next.config.js. La syntaxe est différente, surtout pour les transformations de fichiers et les alias. Consultez la référence de configuration officielle de Turbopack et prévoyez une à deux heures si votre configuration Webpack est complexe.

Turbopack est-il vraiment beaucoup plus rapide ?

Sur les projets que j'ai testés : le démarrage à froid est passé de 12-18 secondes à 3-4 secondes. HMR sur les changements de composants est passé de 1-3 secondes à moins de 200ms dans la plupart des cas. Ce sont des chiffres approximatifs et varieront selon la taille du projet, mais la différence est notable sur tout ce qui n'est pas un projet jouet.

---

La mise à jour vaut le coup. La vitesse de développement de Turbopack à elle seule change votre façon de travailler dans une grande base de code Next.js. Lancez-vous juste en ayant connaissance des changements de cache et des vérifications de compatibilité des bibliothèques tierces, c'est là que la plupart du temps se passe réellement.

Faites-le site par site. Je l'ai fait.

← retour