Next.js - Écrire des applications Javascript universelles.

Server Side Rendering illustration by apptitude

Introduction

Je suis Diogo, jeune ingénieur informatique chez Apptitude et cet article traite d’un sujet d’actualité dans le monde du front-end, qui est les « applications universelles » : applications hybrides, ou tout simplement des applications JS avec rendu côté client et serveur.

Je vais commencer par un bref historique du développement d’applications web et de certains concepts utilisés, et finalement terminer par vous introduire Next.js le framework React pour écrire des applications universelles.

Bien que je cite React.js, ce concept n’est pas propre à cette librairie. D’autres librairies tels que Vue.js ont aussi leurs propre implémentation du concept tels que Nuxt.js.

C’est parti!

 

Les débuts

Parlons de PHP, que le web dynamique a commencé à utiliser dans les années 90. À l’époque, nous construisions des applications web « côté serveur » : c’est-à-dire que tout notre HTML et CSS était généré sur le serveur et ensuite envoyé, pré-rendu, au client pour qu’il n’affiche cette page que selon la structure et le style donné. À chaque fois que l’utilisateur remplissait un formulaire ou modifiait des pages, il déclenchait une requête au serveur.

Ainsi, vous pouviez stocker les données utilisateur et rendre les pages en fonction de celles-ci sur le serveur, mais vous ne pouviez pas facilement faire d’interactions côté client, ce qui signifiait : pas d’animations fantaisistes, de validations complexes, de formulaires dynamiques ou autres. JavaScript était déjà là, mais dans une capacité très limitée et peu de gens l’utilisaient.

Si vous vouliez faire une application web riche, vous deviez utiliser Flash, des applets Java ou une autre technologie similaire de type « plugin », mais c’était assez lourd et il fallait avoir l’extension précédemment installée.

En 2006, JavaScript était sur le point de commencer une nouvelle renaissance avec JQuery : vous pouviez désormais facilement manipuler le DOM, faire des animations et beaucoup d’autres éléments sympathiques ! Les pages commençaient enfin à être pleines de vie et dynamiques.

Le contenu était encore rendu sur le serveur mais pouvait être facilement « augmenté » du côté client grâce à JS et JQuery. Quelques années plus tard – vers 2010 – la première version d’Angular 1.x est sortie et c’était l’un des premiers frameworks Javascript MVC avec lesquels on a commencé à faire ce que nous appelons des « applications single page » (SPA).

 

Qu’est-ce qu’une application single page ?

Il s’agit essentiellement d’un site Web en une page avec toute la logique, les pages et le routage écrits en Javascript. Le site web se comporte comme une application de bureau et récupère ses données via des requêtes Ajax vers une API externe.

Une SPA présente donc les avantages suivants (liste non exhaustive) :

  • Permet de créer des applications Internet riches (Se comporte comme une application de bureau et non plus comme un « site web »).
  • Une fois chargé, la page est plus rapide et les transitions entre les pages sont plus fluides.

Mais elles sont vraiment mauvaises à cause de (liste non exhaustive) :

  • SEO : puisqu’aucun HTML n’est reçu du serveur, les crawlers ne peuvent pas voir beaucoup de données s’ils n’exécutent pas le code Javascript.
  • Temps de démarrage : avec tout ce code à parser et exécuter, les applications sont très lentes à démarrer. Vous ne remarquerez pas la différence sur un ordinateur portable mais vous verrez probablement une page blanche dans votre téléphone pendant quelques secondes ou lorsque vous avez une mauvaise connexion.
  • Les pages peuvent être lourdes car nous allons chercher toutes les ressources dont nous avons besoin.

Une façon de résoudre ce problème est d’utiliser le rendu côté serveur, mais cette fois, nous avons besoin de faire le rendu côté serveur à l’aide de Javascript.

 

Applications Javascript universelles

Nous avons donc besoin de faire des applications Internet riches entièrement en Javascript qui se chargent rapidement, sont adaptées en termes de SEO et plus légères. Comment pouvons-nous faire cela? Nous avons évoqué précédemment le rendu côté serveur et c’est une solution. En d’autres termes, nous devons :

  • Traiter la première requête de l’utilisateur sur le serveur, c’est-à-dire rendre le HTML/CSS, lancer les requêtes Ajax et stocker les résultats en mémoire.
  • Transférer la mémoire du processus (arbre rendu, HTML/CSS et données) au client.
  • Le client prendra l’initiative après la première réponse à la requête.

 

Pourquoi ?

Le serveur a déjà parsé le code et a probablement moins de latence qu’un appareil utilisateur. Ainsi, pour la première demande, le client recevra des données prédéfinies et un pré-rendu HTML/CSS, lui montrant le contenu plus rapidement car il n’a pas besoin d’analyser le code JavaScript pour afficher la première page. De plus, il n’a pas besoin de déclencher une requête Ajax car le backend a déjà récupéré les données nécessaires pour la page en cours.

De cette manière, nous résolvons nos problèmes de temps de démarrage et de référencement (car nous recevons du HTML avec lequel les crawlers peuvent travailler) et nous économisons la bande passante de l’utilisateur car il n’a pas besoin de chercher les données en premier.

Si vous utilisez une bibliothèque de gestion d’états telles que Redux/Vuex/Mobx ou autres, vous pouvez aussi l’utiliser sur le serveur et ensuite « sérialiser » les données pour les traiter sur le client. De plus, ce processus doit être aussi simple et transparent que possible pour le développeur. Pour résumer, les applications Javascript universelles sont des applications qui peuvent fonctionner sur le serveur et le client de façon transparente.

 

Introduction à Next.js

Next.js est un framework React réalisé par Zeit Co, une société de serverless cloud computing. Le framework facilite l’écriture d’applications React universelles et vous permet d’intégrer de belles fonctionnalités telles que :

  • Code splitting : Cela signifie que vous pouvez charger votre code depuis le serveur uniquement quand vous en avez besoin ; vous pouvez le faire par page ou par composant.
  • Routage simple des pages.
  • Exportation statique du site.

Une spécificité de Next.js est que chaque route est une page, comme en PHP simple. Vous avez un dossier « pages » et, si vous avez les fichiers suivants dessus :

Articles.js
Login.js
Dashboard.js

Vous aurez automatiquement les routes suivantes :

/articles
/login
/dashboard

Le code de chaque page sera automatiquement fragmenté, ce qui signifie que si votre utilisateur va directement sur la page /dashboard, il ne récupère que les ressources de cette page et non /items ou /login.

Si nous jetons un coup d’oeil au code d’une page maintenant, disons Dashboard.js :

function Dashboard() {

  return <div>Salut dashboard</div>;

}

Next.js rendra automatiquement ce composant sur le serveur pour chaque premier appel utilisateur : vous en tant que développeur n’aurez plus à vous en soucier.

Dans la plupart des cas, vous voulez récupérer des données initiales lors de l’appel à la page ; Next.js vous donne la possibilité de le faire avec la méthode statique getInitnialProps. Disons que nous souhaitons aller chercher des alarmes sur le tableau de bord, ce sera alors:

function Dashboard({ alarms }) {

  return <div>{alarms.map(a => a.name)}</div>;

}

Page.getInitialProps = async ({ req }) => {

  // Notez que ce code est le même pour le serveur et le client et peut être exécuté dans les deux environnements.

  const res = await api.fetchAlarams(req.authentificaedUser);

  return { alarms: res.alarms };

};


Si l’utilisateur tape /dashboard dans son navigateur, getInitinalProps est d’abord exécuté sur le serveur et les données seront récupérées et rendues de là, avant d’être servies à l’utilisateur. Le code pourra également s’exécuter sur le client, mais seulement lorsque l’utilisateur clique sur un lien pour naviguer vers un autre route.

Si l’utilisateur clique sur un lien pour aller à la page /items, la page Items.js sera rendue sur le client et son getInitialProps sera également déclenché dans le client au lieu du serveur. Vous pouvez donc écrire un code universel pour la récupération de vos données et laisser ensuite le framework décider s’il est exécuté sur le serveur ou le client.

 

Next.js chez Apptitude

Chez Apptitude, nous avons commencé à intégrer Next.js dans tous nos projets JavaScript depuis quelques mois et nous sommes très satisfaits de l’expérience que cela nous offre pour la création de nos applications universelles. Nous l’utilisons avec les librairies suivantes :

Redux et Redux-Saga
Styled-Components
Next-Routes pour les routes plus complexes

Conclusion

Les applications JavaScript universelles sont un moyen de créer des applications web en JavaScript qui sont rapides, faciles à référencer et utilisent une bande passante minimale grâce à des techniques telles que le code splitting et le rendu côté serveur. De nombreuses implémentations sont disponibles pour une variété de librairies/frameworks JavaScript tels que React, Vue, et Angular.

Next.js est un framework qui permet aux développeurs d’écrire facilement des applications universelles avec React de manière transparente, facile et efficace.