Comprendre le fonctionnement du router de NextJS

L'un des intérêts d'utiliser NextJS est son routeur. Depuis la version 9 sont apparut les routes API ainsi que le Dynamic Routing. Avant cela, même si le potentiel de NextJS était très intéressant, il fallait très souvent recourir à une personnalisation de la partie serveur (custom server). Ce n'est plus le cas et il est peu probable d'avoir un intérêt à utiliser un serveur customisé à mon sens. Cela vous fait sortie du contexte que propose NextJS et vous n'êtes pas à l'abris de mauvaises surprises.

Comme c'est un pillier de ce framework, nous allons regarder en détail le fonctionnement de ce routeur.

Une convention autour du dossier "pages" et des noms de fichiers

Lors de l'installation de notre environnement local, nous avons observé qu'il était obligatoire d'avoir un dossier pages. Sans cela, NextJS ne peut pas vous proposer d'afficher une page. Ce serait comme vouloir une page web... sans page web.

Nous devons considérer que le dossier pages est l'équivalent de la racine de votre site.

Pour chaque URL, NextJS va donc rechercher l'équivalent de son arborescence dans votre dossier pages. S'il trouve son chemin, il va ensuite tenter de charger le fichier correspondant à la racine de ce dossier. En JavaScript, c'est toujours le fichier qui se nomme : index.js qui est prioritaire (comme index.php pour PHP).

Dans le cas où il n'existe pas le dernier dossier correspondant à votre recherche, il va tenter de parcourir l'arborescence dans sur l'avant dernier dossier et tenter d'y trouver le fichier qui pourrait porter le nom de la page associée. Ce principe correspond à l'imbrication des fichiers. Pour résumer, chage fichier que vous créez dans le dossier pages correspondra à une route qui aura son URL en équivalent.

Voici quelques exemples qui vont expliquer ce processus :

  • example.com => pages/index.js
  • example.com/profile => pages/profile/index.js Si le fichier n'existe pas, il va tenter de trouver le fichier : pages/profile.js
  • example/page/1 => pages/page/1/index.js. Si le fichier n'existe pas, il va tenter de trouver le fichier : pages/page/1.js

En inversant la vision URL => Page mais plutôt Page => URL :

  • pages/profile/settings/index.js => example.com/profile/settings
  • pages/profile/settings/plan.js => example.com/profile/settings/plan
  • pages/mon-super-article/index.js => example.com/mon-super-article

Ceci est la base du routeur. Evidemment, si on devait s'arrêter ici, vous imaginez bien que ce serait fastidieux de créer toutes les pages notamment lorsque vous avez une pagination ou que vous souhaitez avoir des paramètres dans une URL. Par exemple, le slug de votre article ?

Le routing dynamique

Comme vous avez pu le voir, si vous souhaitez un système de pagination ou jouer sur le slug de votre article pour vos URLs, on ne va pas s'amuser à créer un fichier index.js en permanence. On peut donc utiliser le système de routes dynamiques proposées par NextJS qui utilise les crochets : []

En utilisant les crochets dans votre nom de dossier ou votre nom de fichier, il va faire office de paramètres dans votre URL : [params]. Prenons l'exemple d'un article où vous vous servez de son slug en tant que paramètre dans votre URL. Nous avons 2 solutions :

  • pages/[slug]/index.js
  • pages/[slug].js

Dès lors, une infinité d'URLs vont exister :

  • example.com/mon-article-1
  • example.com/mon-article-2
  • example.com/n-importe-quoi

Toutes ces URLs vont pouvoir matcher avec le fichier correspond que l'on vient de créer en amont.

Allez sur une URL comme la mienne http://localhost:3000/hello-world

Je peux aller sur n'importe quelle URL que j'ai pu vous présenter, celle-ci va "matcher" avec mon fichier [slug].js

Utiliser les paramètres du routeur

Vous avez à votre disposition la possibilité d'accéder au routeur de Next grâce au package : next/router. Il vous expose les fonctionnalités du routeur et va donc nous permettre d'accéder à tout ce qui nous intéresse au sujet du routeur notamment... notre paramètre [slug].

Il est possible de récupérer ce router grâce au hook useRouter (cours sur les hooks) :