Comment mettre en œuvre le rendu côté serveur dans votre application React en trois étapes simples

By Rohit Kumar

Voici ce que nous allons construire dans ce tutoriel : une belle carte React comme celle-ci.

Dans ce tutoriel, nous utiliserons le rendu côté serveur pour délivrer une réponse HTML lorsqu’un utilisateur ou un crawler frappe une URL de page. Nous traiterons ces dernières requêtes côté client.

Pourquoi en avons-nous besoin ?

Laissez-moi vous guider vers la réponse.

Quelle est la différence entre le rendu côté client et le rendu côté serveur ?

Dans le rendu côté client, votre navigateur télécharge une page HTML minimale. Il effectue le rendu du JavaScript et y remplit le contenu.

Le rendu côté serveur, quant à lui, effectue le rendu des composants React sur le serveur. La sortie est un contenu HTML.

Vous pouvez combiner ces deux pour créer une application isomorphe.

Les inconvénients du rendu de React sur le serveur

  • Le RSS peut améliorer les performances si votre application est petite. Mais il peut aussi dégrader les performances si elle est lourde.
  • Il augmente le temps de réponse (et cela peut être pire si le serveur est occupé).
  • Il augmente la taille de la réponse, ce qui signifie que la page prend plus de temps à se charger.
  • Il augmente la complexité de l’application.

Quand devriez-vous utiliser le Server Side Rendering ?

Malgré ces conséquences du SSR, il y a certaines situations dans lesquelles vous pouvez et devez l’utiliser.

SEO

Chaque site web veut apparaître dans les recherches. Corrigez-moi si je me trompe.

Malheureusement, les crawlers des moteurs de recherche ne comprennent pas encore/ne rendent pas JavaScript.

Cela signifie qu’ils voient une page blanche, peu importe à quel point votre site est utile.

Beaucoup de gens disent que le crawler de Google rend maintenant JavaScript.

Pour tester cela, j’ai déployé l’application sur Heroku. Voici ce que j’ai vu sur la Google Search Console:

Le crawler de Google ne rend pas React

Une page blanche.

C’est la plus grande raison pour laquelle j’ai exploré le rendu côté serveur. Surtout quand il s’agit d’une page de pierre angulaire comme une page de destination, un blog, etc.

Pour vérifier si Google rend votre site, visitez :

Le tableau de bord de la console de recherche > Crawl > Fetch comme Google. Entrez l’URL de la page ou laissez-la vide pour la page d’accueil.

Sélectionnez FETCH AND RENDER. Une fois terminé, cliquez pour voir le résultat.

Améliorer les performances

Dans SSR, les performances de l’application dépendent des ressources du serveur et de la vitesse du réseau de l’utilisateur. Cela le rend très utile pour les sites à fort contenu.

Par exemple, disons que vous avez un téléphone mobile de prix moyen avec une vitesse Internet lente. Vous essayez d’accéder à un site qui télécharge 4MB de données avant que vous puissiez voir quoi que ce soit.

Seriez-vous capable de voir quoi que ce soit sur votre écran dans les 2 à 4 secondes ?

Vous visiteriez à nouveau ce site ?

Je ne pense pas.

Une autre amélioration majeure est le temps de première interaction avec l’utilisateur. C’est la différence de temps entre le moment où un utilisateur frappe l’URL et le moment où il voit le contenu.

Voici la comparaison. Je l’ai testé sur un Mac de développement.

React Rendered on Server

Rapport de performance SSR (Chrome)

Le temps de première interaction est de 300ms. L’hydrate se termine à 400ms. L’événement de chargement se termine à 500ms environ. Vous pouvez le constater en consultant l’image ci-dessus.

React Rendered on Client’s Browser

Client side performance report (Chrome)

Le premier temps d’interaction est de 400ms. L’événement de chargement sort à 470ms.

Le résultat parle de lui-même. Il y a une différence de 100ms dans le temps de première interaction avec l’utilisateur pour une si petite application.

Comment ça marche ? – (4 étapes simples)

  • Créer un Redux Store frais à chaque demande.
  • Optionnellement dispatcher quelques actions.
  • Gagner l’état hors du Store et exécuter SSR.
  • Envoyer l’état obtenu à l’étape précédente avec la réponse.

Nous utiliserons l’état passé dans la réponse pour créer l’état initial côté client.

Avant de commencer, clonez/téléchargez l’exemple complet depuis Github et utilisez-le comme référence.

Démarrer en configurant notre application

D’abord, ouvrez votre éditeur et votre shell préféré. Créez un nouveau dossier pour votre application. Commençons.

npm init --yes

Remplir les détails. Après la création de package.json, copiez-y les dépendances et les scripts ci-dessous.

Installez toutes les dépendances en exécutant :

npm install

Vous devez configurer Babel et webpack pour que notre script de construction fonctionne.

Babel transforme ESM et react en code compris par Node et le navigateur.

Créez un nouveau fichier .babelrc et mettez-y la ligne ci-dessous.

{ "presets": }

webpack regroupe notre app et ses dépendances dans un seul fichier. Créez un autre fichier webpack.config.js avec le code suivant dedans:

const path = require('path');module.exports = { entry: { client: './src/client.js', bundle: './src/bundle.js' }, output: { path: path.resolve(__dirname, 'assets'), filename: ".js" }, module: { rules: }}

Le processus de construction produit deux fichiers:

  1. assets/bundle.js – application côté client pur.
  2. assets/client.js – compagnon côté client pour SSR.

Le dossier src/ contient le code source. Les fichiers compilés Babel vont dans views/. Le répertoire views sera créé automatiquement s’il n’est pas présent.

Pourquoi avons-nous besoin de compiler les fichiers sources ?

La raison est la différence de syntaxe entre ESM & CommonJS. En écrivant React et Redux, nous utilisons fortement import et export dans tous les fichiers.

Malheureusement, ils ne fonctionnent pas dans Node. C’est là que Babel vient à la rescousse. Le script ci-dessous indique à Babel de compiler tous les fichiers dans le répertoire src et de mettre le résultat dans views.

"babel": "babel src -d views",

Maintenant, Node peut les exécuter.

Copie des fichiers statiques précodés &

Si vous avez déjà cloné le dépôt, copiez à partir de celui-ci. Sinon, téléchargez le fichier ssr-static.zip depuis Dropbox. Extrayez-le et conservez ces trois dossiers à l’intérieur de votre répertoire app. Voici ce qu’ils contiennent.

  1. React App et les composants résident dans src/components.
  2. Fichiers Redux dans src/redux/.
  3. assets/ & media/ : Contenir les fichiers statiques tels que style.css et les images.

Côté serveur

Créer deux nouveaux fichiers nommés server.js et template.js à l’intérieur du dossier src/.

src/server.js

La magie se produit ici. C’est le code que vous avez cherché.

import React from 'react';import { renderToString } from 'react-dom/server';import { Provider } from 'react-redux';import configureStore from './redux/configureStore';import App from './components/app';module.exports = function render(initialState) { // Model the initial state const store = configureStore(initialState); let content = renderToString(<Provider store={store} ><App /></Provider>); const preloadedState = store.getState(); return { content, preloadedState };};

Au lieu de rendre notre application, nous devons l’envelopper dans une fonction et l’exporter. La fonction accepte l’état initial de l’application.

Voici comment cela fonctionne.

  1. Passe initialState à configureStore(). configureStore()renvoie une nouvelle instance de Store. Maintenez-la à l’intérieur de la variable store.
  2. Appelle la méthode renderToString(), en fournissant notre App en entrée. Elle rend notre app sur le serveur et retourne le HTML produit. Maintenant, la variable content stocke le HTML.
  3. Sortir l’état du Redux Store en appelant getState() sur store. Gardez-le dans une variable preloadedState.
  4. Retournez les content et preloadedState. Nous les passerons à notre modèle pour obtenir la page HTML finale.

2. src/template.js

template.js exporte une fonction. Elle prend title, state et content en entrée. Elle les injecte dans le modèle et renvoie le document HTML final.

Pour transmettre l’état, le modèle attache state à window.__STATE__ à l’intérieur d’une balise <script>.

Maintenant vous pouvez lire state du côté client en accédant à window.__STATE__.

Nous incluons également l’application côté client du compagnon SSR assets/client.js dans une autre balise de script.

Si vous demandez la version client pure, elle ne met que assets/bundle.js à l’intérieur de la balise de script.

Le côté client

Le côté client est assez simple.

src/bundle.js

C’est ainsi que vous écrivez l’enveloppement React et Redux Provider. C’est notre pure application côté client. Pas d’astuces ici.

import React from 'react';import { render } from 'react-dom';import { Provider } from 'react-redux';import configureStore from './redux/configureStore';import App from './components/app';const store = configureStore();render( <Provider store={store} > <App /> </Provider>, document.querySelector('#app'));

src/client.js

Cela vous semble familier ? Oui, il n’y a rien de spécial sauf window.__STATE__. Tout ce que nous devons faire est de récupérer l’état initial de window.__STATE__ et de le passer à notre fonction configureStore() comme état initial.

Regardons notre nouveau fichier client:

import React from 'react';import { hydrate } from 'react-dom';import { Provider } from 'react-redux';import configureStore from './redux/configureStore';import App from './components/app';const state = window.__STATE__;delete window.__STATE__;const store = configureStore(state);hydrate( <Provider store={store} > <App /> </Provider>, document.querySelector('#app'));

Regardons les changements:

  1. Remplacer render() par hydrate(). hydrate() est identique à render() mais est utilisé pour hydrater les éléments rendus par ReactDOMServer. Il garantit que le contenu est le même sur le serveur et le client.
  2. Lire l’état de l’objet global de fenêtre window.__STATE__. Stockez-le dans une variable et supprimez le window.__STATE__.
  3. Créer un nouveau magasin avec state comme initialState.

Tout est fait ici.

Mettre tout ensemble

Index.js

C’est le point d’entrée de notre application. Il gère les requêtes et le templating.

Il déclare également une variable initialState. Je l’ai modélisée avec les données du assets/data.json fichier. Nous la passerons à notre fonction ssr().

Note : En faisant référence à un fichier qui est à l’intérieur de src/ à partir d’un fichier à l’extérieur de src/ , utilisez le require() normal et remplacez src/ par views/. Vous connaissez la raison (compilation Babel).

Routing

  1. / : Page d’accueil avec rendu serveur par défaut.
  2. /client : Exemple de rendu côté client pur.
  3. /exit : Bouton d’arrêt du serveur. Disponible uniquement en développement.

Build & Run

Il est temps de construire et d’exécuter notre application. Nous pouvons le faire avec une seule ligne de code.

npm run build && npm run start

Maintenant, l’application s’exécute à http://localhost:3000.

Prêts à devenir un React Pro ?

Je commence une nouvelle série à partir de lundi prochain pour faire flamber vos compétences React, immédiatement.

lien d’abonnement ci-dessous ?

Merci de lire ceci.

Si vous l’aimez et que vous le trouvez utile, suivez-moi sur Twitter & Webflow.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.