4. Exemple [nuxt-01] : routage et navigation
Nous allons construire une série d’exemples simples pour découvrir progressivement le fonctionnement d’une application [nuxt]. Nous allons commencer par porter l’application [vuejs-11] du document |Introduction au framework *VUE.JS* par l’exemple|, pour découvrir tout d’abord ce qui différencie l’organisation du code d’une application [nuxt] de celle du code d’une application [vue].
4.1. Arborescence du projet
Le projet [vuejs-11] était un projet de navigation entre vues :

L’arborescence du code source du projet [vuejs-11] était le suivant :

- [main.js] était le script exécuté lors du démarrage de l’application [vue] ;
- [router.js] fixait les règles de routage ;
- [App.vue] était la vue structurante de l’application. Elle organisait la mise en page des différentes vues ;
- [Component1, Component2, Component3, Layout, Navigation] étaient les composants utilisés dans les différentes vues de l’application ;
Dans le portage de l’application [vue] [1] vers une application [nuxt] [2] :
- les scripts exécutés au démarrage de l’application doivent être déclarés dans la clé [plugins] du fichier [nuxt.config.js]. Par ailleurs, il est possible de séparer les scripts destinés au serveur [nuxt] de ceux destinés au client [nuxt] ;
- la vue [App.vue] doit être installée dans le dossier [layouts] et être renommée [default.vue] ;
- les composants [Component1, Component2, Component3] qui sont les cibles du routage doivent migrer dans le dossier [pages]. L’un d’eux, celui qui sert de page d’accueil, doit être renommé [index.vue]. Nous avons ici renommé les fichiers :
- [Component1] --> [index] : affiche le texte [Home] ;
- [Component2] --> [page1] : affiche le texte [Page 1] ;
- [Component3] --> [page2] : affiche le texte [Page 2] ;
[nuxt] utilise le contenu du dossier [pages] pour générer dynamiquement les routes suivantes :
Du coup, le fichier [router.js] utilisé dans le projet [vue] devient inutile dans le projet [nuxt].
Le fichier de configuration [nuxt.config.js] sera le suivant :
- ligne 62 : on indique le dossier qui contient le code source du projet [dvp] ;
- ligne 66 : : on indique l’URL racine de l’application [dvp] (on peut mettre ce qu’on veut) ;
- ligne 43 : notons que la bibliothèque [bootstrap-vue] est référencée dans la configuration ;
4.2. Portage du fichier [main.js]
Le fichier [main.js] du projet [vuejs-11] était le suivant :
En-dehors des [imports], le code fait les choses suivantes :
- lignes 5-11 : utilisation de la bibliothèque [bootstrap-vue]. Ce travail est désormais fait par le module [bootstrap-vue/nuxt] de la ligne 43 du fichier de configuration [nuxt.config.js] ;
- lignes 14 et 25 : utilisation du fichier de routage [router.js]. Ce travail est désormais fait automatiquement par l’application [nuxt] à partir de l’arborescence du dossier [pages] ;
- lignes 20-26 : instanciation de la vue principale de l’application. Dans une application [nuxt], c’est la vue [layouts/default.vue] qui sert de vue principale ;
Le fichier [main.js] n’a désormais plus de raison d’être. S’il en avait eu une, on l’aurait déclaré dans la clé [plugins] de la ligne 30 du fichier de configuration [nuxt.config.js] ;
4.3. La vue principale [default.vue]

La vue principale [layouts / default.vue] est la suivante :
- ligne 9, dans le projet [vuejs-11], on avait la balise <router-view /> au lieu de la balise <nuxt /> utilisée ici. Les deux semblent utilisables. Je les ai essayées toutes les deux sans voir de changement. J’ai gardé la balise <nuxt /> qui est celle conseillée. Elle affiche la vue courante, ç-à-d la page cible du routage courant ;
4.4. Les composants

Par rapport au projet [vuejs-11], les composants [layout, navigation] ne changent pas :
[components / layout.vue]
Ce composant sert à structurer les pages de l’application en deux colonnes :
- lignes 7-9 : la colonne de gauche sur 2 colonnes Bootstrap ;
- lignes 11-13 : la colonne de droite sur 10 colonnes Bootstrap ;
[navigation.vue]
Ce composant affiche trois liens de navigation :

Pour savoir quoi mettre comme valeur aux attributs [to] des lignes 4, 7 et 10, il faut regarder le dossier [pages] [2] :
- la page [index] aura l’URL [/] ;
- la page [page1] aura l’URL [/page1] ;
- la page [page2] aura l’URL [/page2] ;
Le composant [navigation] peut être également écrit de la façon suivante :
La balise <b-nav-item> est remplacée par la balise <nuxt-link> qui désigne un lien de routage. A l’exécution, je n’ai pas vu de grande différence, rien qui pourrait faire pencher la balance vers une balise plutôt que l’autre.
4.5. Les pages

La page [index.vue] affiche la vue suivante :

Le code de la page est le suivant :
- ligne 5 : le composant de navigation est placé en colonne de gauche ;
- lignes 7-9 : une alerte est placée dans la colonne de droite ;
Dans la partie <script>, nous mettons du code dans les fonctions du cycle de vie de la page [beforeCreate, created, beforeMount, beforeMounted]. Nous voulons savoir lesquelles sont exécutées par le serveur []nuxt et lesquelles par le client [nuxt]. On rappelle deux choses :
- lorsqu’une page est demandée soit au démarrage de l’application, cas de la page [index], soit manuellement par l’utilisateur qui rafraîchit la page du navigateur ou tape une URL à la main, elle est délivrée d’abord par le serveur [nuxt]. Celui-ci interprète le code ci-dessus et exécute le Javascript qu’il contient ;
- lorsque la page envoyée par le serveur [nuxt] arrive sur le navigateur, elle arrive avec le code du client [nuxt]. Celui-ci interprète de nouveau la page ci-dessus ;
- par des logs, on veut savoir qui fait quoi pour mieux comprendre ce processus ;
- lignes 30-31 : on utilise dans la fonction un objet global [process] qui existe aussi bien sur le serveur que sur le client :
- [process.server] est vrai si le code est exécuté par le serveur, faux sinon ;
- [process.client] est vrai si le code est exécuté par le client, faux sinon ;
- parce que la variable [process] est non déclarée dans le code, on est obligés de mettre la ligne 14 pour [eslint]. La ligne [16] est nécessaire parce que sinon [eslint] déclare un autre type d’erreur à cause de la variable [process]. La ligne 15 est elle nécessaire pour permettre l’utilisation de [console] dans les fonctions du cycle de vie ;
- ligne 29 : on veut savoir également si les fonctions du cycle de vie reçoivent des arguments. On va découvrir en effet que [nuxt] transmet des informations à certaines fonctions. On veut savoir si les fonctions du cycle de vie en font partie ;
- on répète le même code pour les quatre fonctions ;
4.6. Le fichier [nuxt.config.js]
C’est lui qui contrôle l’exécution du projet [dvp]. Il a été décrit page 32.
4.7. Exécution du projet
Nous exécutons le projet :

La page affichée est la suivante :

Une fois installée sur le navigateur, l’application [nuxt] devient une application [vue] classique. Nous ne commenterons donc pas le fonctionnement client de l’application [nuxt-01]. Cela a été fait dans le projet [vuejs-11] du document |Introduction au framework *VUE.JS* par l’exemple|.
L’application [nuxt] ne diffère de l’application [vue] qu’à deux moments :
- le démarrage initial de l’application qui fournit la page d’accueil ;
- à chaque fois que l’utilisateur provoque d’une manière ou une autre le rafraîchissement du navigateur ;
Dans ces deux cas :
- la page demandée est fournie par le serveur ;
- la page reçue est traitée par le client ;
Regardons les logs du démarrage de l’application (F12 sur le navigateur) :

- en [1], les logs du serveur (process.server=true). Ils apparaissent précédés de la mention [Nuxt SSR] (SSR= Server Side Rendered) ;
- en [2], les logs du client sur le navigateur (process.client=true) ;
De ces logs, on peut déduire que :
- le serveur exécute les fonctions [beforeCreate, created] du cycle de vie ;
- le client exécute les fonctions [beforeCreate, created, beforeMount, mounted] du cycle de vie ;
- le serveur a traité la page avant le client ;
- dans les deux cas, aucune des fonctions exécutées ne reçoit d’arguments ;
Maintenant regardons le code source de la page reçue (option [Code source de la page] dans le navigateur) :
Commentaires
- la première chose qui peut être remarquée est que le code HTML reçu reflète correctement ce que voit l’utilisateur. Ce n’était pas le cas des applications [vue] pour lesquelles le code source affiché était le code source d’un fichier HTML quasi vide. C’était ce qu’avait reçu le navigateur. Ensuite le client [vue] prenait la main et construisait la page attendue par l’utilisateur. Il fallait alors aller dans l’onglet [inspecteur] des outils de développement du navigateur (F12) pour découvrir le code HTML de la page affichée ;
- lignes 57-67 : c’est le script qui a affiché les logs tagués [Nuxt SSR]. Ces logs ont été produits côté serveur et les résultats ont été embarqués dans un script inclus dans la page envoyée ;
- lignes 68-71 : les scripts qui forment le client exécuté côté navigateur ;
Les scripts des lignes 68-71 sont exécutés et transforment la page reçue. Pour connaître la page finalement affichée pour l’utilisateur, il faut aller dans l’onglet [inspecteur] des outils de développement du navigateur (F12) :

Lorsqu’on développe la balise <html> [3], on a le contenu suivant :
Commentaires
- à première vue, la page affichée lignes 19-59, semble être la même que la page reçue ;
- lignes 14-16 : trois nouveaux scripts apparaissent, un pour chacune des pages de l’application ;
- lignes 76-79 : quatre [iframe] apparaissent ;
Lignes 33, 37 et 42, les liens posent problème. Ils semblent être des liens normaux qui lorsqu’on les clique vont faire une requête vers le serveur. Or à l’exécution, on voit que ce n’est pas vrai : il n’y a pas de requête vers le serveur. Pour comprendre pourquoi, il faut retourner dans l’onglet [inspecteur] du navigateur :

On voit qu’en [1, 2] des événements ont été attachés aux liens. Ce sont les scripts des lignes 71-74 qui ont attaché des gestionnaires d’événements aux liens. Donc :
- la page affichée par le client est visuellement identique à celle envoyée par le serveur ;
- un comportement dynamique a été ajouté à la page par le client ;
Maintenant demandons la page [page1] en tapant l’URL à la main [http://192.168.1.128:81/nuxt-01/page1]. Les logs deviennent les suivants :

On obtient les mêmes résultats que pour la page [index] mais pour [page1]. Le code source de la page reçue est lui le suivant :
On obtient le même type de page que la page [index] mais avec l’alerte de la vue [Page 1] (ligne 30). Lignes 41-44, le code du client a été renvoyé avec la page. Au final, demander une URL à la main est identique à redémarrer l’application. Simplement la page affichée n’est pas forcément la page d’accueil, c’est celle qui a été demandée. Une fois la page reçue, c’est le client qui prend la main. Le serveur ne sera plus sollicité à moins que l’utilisateur n’en décide autrement.