Migration vers Next.Js 13 : Retour d’expérience


TL;DR
La nouvelle version de Next.js apporte des nouveautés très intéressantes en terme de performances, mais l'expérience de développement s'en trouve un peu dégradée. Heureusement, on peut s'attendre à des améliorations prochainement.
Table des matières
En Octobre 2022 sortait avec force et fracas la version 13 de Next.js, le framework de React.js.
Si des optimisations de performances on été promises, cette version a surtout fait parler d’elle pour les profondes modifications qu’elle apportait au fonctionnement des app Next.js, et qui ne faisaient pas toujours l’unanimité.
Alors ces critiques étaient-elles fondées ? Après plusieurs semaines à tester ces nouveautés, je vous propose un retour d’expérience honnête.
Une migration vers Next.js 13 qui prend du temps
Pour commencer, il faut noter que cette mise à jour apporte vraiment beaucoup de nouveautés : le nouveau répertoire /app
avec ses layouts, le passage à React 18 avec les React Server Components (RSC) ou encore une des nouvelles API pour next/image
et next/link
.
Même si on peut se réjouir de voir autant d’évolutions, cela fait quand même beaucoup de changements pour une même mise à jour !
Le plus long étant de migrer vos pages dans le nouveau dossier /app
.
Pour ma part, j’avais 7 pages à migrer, et cela m’a pris quasiment une journée, alors je n’ose imaginer pour les gros projets !
Heureusement, il est possible de faire ces changements de manière incrémentale, c’est à dire que vous pouvez migrer vos pages une par une, et garder un dossier page en même temps que votre dossier /app
.
L’autre bonne nouvelle, c’est que la doc pour migrer est plutôt exhaustive, et rend le processus presque indolore.
Mais au fait, pourquoi c’est si long ?
Le dossier /app
, de bonnes promesses, mais pas toujours évident dans la pratique
Lorsque vous transférez vos pages vers le dossier /app
, vous ne pouvez pas juste copier/coller vos composants.
En effet, de nouvelles conventions de structure ont été apportées, avec la promesse d’améliorer le routing et la gestion des layouts dans Next.js.
Ainsi, dans le dossier /app
, le nommage des fichiers est important. Désormais, chaque dossier définit une route, et il y a en plus des noms de fichier réservés, qui sont censés améliorer l’expérience de développement.
Le fichier page.tsx
Pour commencer, avec la version 13 de Next.js, vous devez créer un dossier contenant un fichier page.tsx
pour définir une route. Il s’agit d’un Server Component qui doit retourner votre page, nous y reviendrons.
Le fichier head.tsx
Ensuite, pour chaque page, vous devez définir un fichier head.tsx
pour vos balises title, meta, ou tout ce qui se trouve normalement dans une balise head.
Si aucun fichier head.tsx
n’est présent, alors la page utilisera celui de la page parente la plus proche. Cela qui signifie que vous devez au moins spécifier un fichier head.tsx
à la racine de votre dossier /app
.
À noter que les fichier head.tsx
ne sont pas fusionnés entre eux. Ainsi, si vous souhaitez partager une balise meta entre vos pages, vous devrez la spécifier dans chaque fichier head.tsx
.
C’est pratique car cela vous offre un contrôle granulaire de vos pages, mais il ne faut pas oublier d’intégrer vos balises dans chaque fichier head.tsx
.
Les fichiers loading.tsx et error.tsx
Vous pouvez désormais aussi créer des fichiers loading.tsx
et error.tsx
pour gérer l’état de chargement et d’erreur de vos pages. Rien de particulier à signaler sur cette nouveauté, si ce n’est que cela peut paraître un peu redondant de devoir recréer des fichiers pour chaque route.
La fichier layout.tsx
Enfin, l’autre grosse nouveauté, c’est la gestion des layouts avec le fichier spécial layout.tsx
.
Vous pouvez donc en définir un pour chaque page, sachant que les layouts sont “imbriqués” par défaut, c’est à dire que chaque page héritera également des layouts de pages parentes.
Vous pouvez faire des requêtes depuis le layout, ce qui est pratique si vous voulez afficher un menu avec des catégories récupérées depuis votre CMS par exemple.
De plus, si vous faites plusieurs fois la même requête dans votre arbre de composant, elles seront automatiquement mises en cache par React, pour éviter de les appeler plusieurs fois. C’est le principe de request deduping.
Dans la pratique, voilà ce à quoi peut ressembler un dossier /app
:
Je trouve que cette nouvelle structure apporte du bon et du moins bon. Par exemple, avoir plusieurs fichiers portant exactement le même nom peut porter à confusion lorsque vous en avez plusieurs d’ouverts en même temps.
Autrement, il faudra simplement s’habituer à ces nouvelles conventions.
Abordons maintenant une autre nouveauté qui a fait couler beaucoup d’encre : les RSC.
Les React Server Components (RSC), une fausse bonne idée ?
Par défaut, tous les composants dans le dossier app sont des Server Components, c’est à dire qu’ils sont exécutés côté serveur. C’est utile pour récupérer des données, comme vous pouviez le faire auparavant avec les fonctions getStaticProps
ou getServerSideProps
.
Comment fonctionnent les RSC ?
L’intérêt d’avoir des Server Components c’est, entre autre, de réduire le poids du Javascript chargé côté client, et donc offre un chargement plus rapide des pages.
Mais du coup, vous n’avez pas accès aux fonctions de code client, comme useEffect()
ou useState()
, et vous ne pouvez pas écrire du jsx directement.
Il vous faudra donc créer un fichier page.tsx
dont le seul but est de retourner votre composant client.
Voici ce que cela donne concrètement :
1async function getPosts() {
2return await fetch('https://myenspapi/posts')
3}
4
5// Votre Server Component
6export default async function Page() {
7// Ici, faites ce que vous voulez côté serveur, typiquement récupérer des données
8const posts = await getPosts();
9
10return <HomePage posts={posts} />; // Ici on retourne le Client Component
11}
Rien de très compliqué, mais ça demande un petit travail de réécriture de toutes vos fonctions getStaticProps
et getServerSideProps
.
À noter que par défaut, vos pages seront générées de manières statiques, mais vous pouvez toujours opter pour une génération dynamique (Server Side Rendering).
Cela se fait automatiquement lorsque vous utilisez une fonction dynamique dans votre page, c’est à dire une fonction qui a besoin de connaître les paramètres de la requête, comme headers()
ou cookies()
.
Ou alors, vous pouvez forcer la génération dynamique en spécifiant la variable revalidate
ou cache
au niveau d’une requête, ou bien de votre page.
Je ne rentrerai pas trop dans les détails ici, je dois avouer que cette nouvelle API m’a semblé un peu complexe à prendre en main, mais on s’y habitue, et encore une fois, la doc est très claire.
Le problème avec les RSC
Même si ces nouveautés apportent un gain de performance, le principal souci des RSC est qu’ils dégradent potentiellement l’expérience développeur (DX).
En effet, les frontières sont un peu brouillées entre les tâches à faire côté client ou serveur, et il faut maintenant apprendre à mixer des composants clients et serveurs entre eux, ce qui est propice à plus d’erreurs.
Néanmoins, les RSC sont encore en phase de développement, et on peut espérer des améliorations dans le futur.
Par ailleurs, je pense que je n’ai pas encore saisi toutes les subtilités des RSC, et que dans quelques temps, leur utilisation me paraîtra plus intuitive.
Conclusion : mon avis sur Next.js 13
Pour conclure, cette version apporte des fonctionnalités très intéressantes et permet à Next.js de rester à la pointe des frameworks javascript.
Cependant, il vous faudra un peu de temps pour assimiler tous ces changements, et j’ai peur que l’expérience de développement soit parfois un peu dégradée.
Pour ma part, la migration a été quelque peu fastidieuse, mais si vous êtes déjà habitués à React 18 et les RSC, peut-être que vous aurez moins de difficultés que moi. De plus, vous pouvez vous appuyer sur une documentation très solide.
En revanche, cette nouvelle version est encore très jeune, d’ailleurs certaines fonctionnalités sont encore en beta.
Cela a deux implications.
D’abord, certaines libraries et packages npm n’ont pas encore été mises à jour pour être compatible avec Next.js 13.
Ensuite, peu de développeurs ont adopté cette version, il y a donc moins de personnes susceptibles de vous aider si vous rencontrez un bug.
Cela devrait rapidement changer, mais si vous avez une grosse application, je vous recommanderais de prendre votre temps.
En tout cas, pour ceux qui voudrait franchir le pas, bon courage !
Et si vous souhaitez obtenir de l’aide pour migrer votre site, n’hésitez pas à nous contacter par mail ou via Linkedin.