Le blog des décideurs du digital sur toutes les tendances tech, architecture, organisation et produit

Le Server Side Rendering : optimiser la performance et le SEO de vos applications Vue.js, React ou Angular

Avec le succès des frameworks front JavaScript modernes comme Vue.js, React ou Angular, de nombreuses applications web sont actuellement des Single Page Apps (SPA). L'interface utilisateur, c'est-à-dire le contenu HTML des pages web, y est générée par le navigateur, on nomme donc ce fonctionnement client-side rendering (CSR) ou rendu côté client.

Avant l'apparition des SPA, le contenu HTML était renvoyé par le serveur, soit directement de manière statique, soit généré par un langage serveur (en PHP, Java, Python). Ce fonctionnement se nomme server-side rendering (SSR) ou rendu côté serveur. Dans ce cas, à chaque changement de page, c’est le serveur qui renvoie tout le contenu HTML.

Une application rendu coté client est interactive et dynamique. Une fois le JavaScript chargé, tout est exécuté coté navigateur : la navigation est rapide, il n’y a plus de chargement du contenu à chaque changement de page. Cependant, elle présente aussi certaines limitations :

  • Une optimisation compliquée du référencement ou SEO
  • Un temps de chargement initial plus élevé

Dans cet article, nous verrons qu’un nouveau mode de fonctionnement, les applications universelles, permet de combiner le meilleur du rendu côté serveur et du rendu côté client. 

bill-jelen-woWf_VJ7dNs-unsplash

 

Les limites du rendu côté client

Bien comprendre

Voyons concrètement le fonctionnement d’une application Vue.js, React ou Angular :

schema-csr

Au chargement de la page, le serveur envoie une réponse HTML au navigateur qui contient littéralement très peu de code HTML, à savoir un placeholder :

<div id="root"></div>

Dans cette réponse se trouvent aussi les scripts JavaScript à télécharger. Le navigateur commence donc à les télécharger. En attendant, la page ne contient pas plus de code HTML, c’est une page blanche.

Une fois le JavaScript chargé, il est exécuté par le navigateur et génère le HTML qui va être affiché par le navigateur : la page est visible et intéractive.

On relève donc 2 problèmes majeurs.

Problème n°1 : pas de HTML donc des mauvais résultats SEO

Notre page ne contient au premier rendu qu’un placeholder. Les robots des moteurs de recherche ne lisent donc aucun contenu sur la page.

Cela signifie que Facebook, Twitter, Bing, Google, tous les moteurs de recherche ne peuvent donc pas décrire notre site web d’un point de vue SEO. En effet, les robots des résultats de recherche lisent très mal le JavaScript.

Ils rencontrent aussi des difficultés pour explorer les autres pages car le routing de l’application est en JavaScript. De plus, lire du JavaScript consomme beaucoup plus de ressources que de lire du HTML, les coûts sont donc plus élevés. C’est pourquoi les sites rendus côté client sont crawlés moins régulièrement.

Indexer une SPA est donc soit impossible soit compliqué, et les performances SEO qui en résultent sont mauvaises.

Problème n°2 : un temps de chargement initial élevé

Comme nous l’avons dit, pendant que le navigateur télécharge puis exécute le JavaScript, l’utilisateur ne voit qu’une page blanche. Celle-ci peut être remplacée par une page de chargement. Toutefois, l’utilisateur ne voit rien d’autre et doit attendre la fin du téléchargement.

Ce phénomène peut prendre une dimension encore plus importante dans les cas où :

  • L’utilisateur a une connexion internet lente, en particulier sur mobile
  • L’utilisateur utilise un appareil peu puissant, par exemple un appareil mobile d'ancienne génération.
  • L’utilisateur utilise une vieille version peu performante d’un navigateur

Dans un souci de délivrer une expérience optimisée pour tous les utilisateurs, sur tous les devices et à tout moment, ce problème prend une dimension critique.

 

Un retour au rendu côté serveur ?

Bien comprendre

Les problèmes du rendu côté client peuvent être résolus en rendant notre application Vue.js, React ou Angular, coté serveur :

schema-ssr

Contrairement au rendu côté client, le JavaScript est rendu côté serveur et la réponse envoyée au navigateur contient directement tout le code HTML généré. La page est donc visible dès la première requête au serveur(elle n’est pas encore interactive).

Dans un second temps, comme pour le rendu côté client, le navigateur télécharge le JS puis l’exécute afin de rendre la page interactive.

La différence principale du rendu côté serveur d’un point de vue utilisateur est donc de réduire le phénomène de page blanche, en affichant immédiatement tout le contenu statique de la page. De plus, les requêtes effectuées côté serveur sont souvent plus stables et plus rapides.

Quels résultats ?

ReactiveSearch (UI components library for Elasticsearch) après implémentation du SSR : “On an average, first meaningful paint for apps solely built with reactivesearch is ~50% faster (on a slow 3G network)”

Le premier rendu (first meaningful paint) est donc effectivement bien plus rapide comme prévu. De plus, peu importe la vitesse de connexion ou la puissance du device, le rendu est fait côté serveur et dépend donc de la puissance du serveur. Néanmoins, l’interactivité (time to interactive) prend un peu plus de temps puisqu’il faut réaliser plus d’opérations (notamment la génération du HTML côté serveur) qu’en rendu côté client avant d'exécuter le JavaScript.

Walmart labs : “When we did A/B tests on SSR vs CSR, the trend above is what we would see, and our numbers showed better engagement from the customer with rendering early”

Le rendu côté serveur prend donc tout son sens quand il faut afficher des résultats le plus vite possible et quand l’interactivité de la page n’est pas la priorité numéro un. C’est le cas du e-commerce par exemple.

 

Le meilleur des deux mondes : les applications universelles

Allier rendu côté serveur et rendu côté client

Allier la vitesse du chargement initial grâce au rendu côté serveur et l'interactivité des SPA est aujourd’hui très facile. Il suffit de ne rendre coté serveur que la landing page (première page visitée) sur laquelle l’utilisateur se rend puis de laisser la main au rendu côté client pour le reste de la navigation. Et cela porte un nom : application universelle (ou isomorphique).

On combine ainsi les avantages des deux types de rendu y compris les performances SEO puisque les robots d’indexation visitent les pages une par une. Ils profitent donc uniquement du rendu côté serveur.

Quels Frameworks ?

Pour chacun des 3 frameworks Vue.js, React ou Angular, il existe un framework d’application universelle associé.

Nuxt.js : C’est le framework Vue.js qui permet de développer des applications universelles.

Next.js : C’est le framework React qui permet de développer des application universelles.

Nuxt.js et Next.js font en fait bien plus. Ils proposent une excellente structure et organisation par défaut. Leur rapidité de configuration apportent une expérience de développement très appréciable aux développeurs. Ces deux frameworks vont encore plus loin sur la SEO et proposent des outils pour implémenter facilement les bonnes pratiques (robots.txt, sitemap, meta,...) 

Angular universal : C’est le framework Angular pour les applications universelles. Même s’il est moins en vogue que ses concurrents, il est aussi possible de faire du SSR en Angular.

A Theodo, nous avons choisi d’orienter notre expertise en Nuxt.js pour plusieurs raisons :

  • La qualité de la documentation
  • Des choix de développement pragmatiques tels qu’un routing géré automatiquement à partir de l'arborescence des pages, ou un store directement intégré pour partager l’état global de l’application
  • Une structure de l’application standard qui permet de former rapidement les développeurs Vue.js que nous intégrons à nos équipes
  • La rapidité de mise en place d’un nouveau projet grâce à un générateur qui met en place toutes les bonnes pratiques de code : create-nuxt-app
  • Plusieurs modes disponibles : universal ou SPA 

 

Pour aller plus loin

D’autres solutions, que nous n’avons pas encore évoquées, permettent d’améliorer encore la performance de nos applications universelles.

Caching HTTP

Certaines pages ne sont que rarement mises à jour. Elles peuvent alors être mises en cache. Avec du rendu côté serveur, pourquoi ne pas en profiter pour mettre en cache côté serveur ces pages. Cela évite de répéter les requêtes faites au serveur et conserve les avantages d’une application universelle.

Si le HTML de chaque landing page est en cache, les avantages SEO sont conservés. Et chaque landing page cachée est rendue encore plus vite. On conserve ensuite le fonctionnement SPA pour le reste de l’application.

Prerendering

Un autre mode de fonctionnement de Nuxt.js existe. Il permet de générer un site entièrement statique. Dans ce cas, pas besoin de serveur pour rendre les pages à la volée, elles sont toutes prérendues en HTML. Le fonctionnement reste ensuite le même côté client, c’est une SPA.

Néanmoins cette solution n’est pas utilisable pour des urls dynamiques. De plus, si l’application accède à des données externes, à chaque changement des données, l’application doit être régénérée pour être à jour.

Progressive Booting

Le principal temps à améliorer est le moment où la page est rendue interactive. C’est donc le temps du téléchargement du JavaScript qui est à améliorer. Pourquoi charger tout le JavaScript d’un coup ? En le séparant en différents morceaux, on pourrait permettre à l'utilisateur d’interagir progressivement avec la page.

Il faut donc être capable de prioriser le chargement des différents blocs de notre application, et de les charger progressivement. Ceci peut se nommer le progressive booting. Il garde l’avantage du rendu côté serveur pour le premier rendu de la page, puis il accélère le temps d’attente avant interaction avec la page.

 

 

 

Topics: Front End