Makina Blog
SEO : indexer une application Javascript
Comment utiliser le code de votre application pour un rendu server-side.
Un des enjeux fondamentaux du développement web ces dernières années est l'indexation des applications Javascript par les moteurs de recherche.
Notamment, depuis que Google a annoncé déprécier l'indexation "Ajax-crawling scheme", c'est à dire utilisant des fragments spécifiques de l'URL, de nombreuses expériences ont lieu pour tenter de déterminer les capacités réelles d'indexation du moteur de recherche dominant.
On a pu notamment lire une très interessante comparaison des frameworks Javascript :
Et donc, si Google annonce régulièrement qu'il interprète le Javascipt, on constate en réalité que le principe souffre de certaines limitations :
- Seul le contenu présent dans la page lors de l'événement load est indexé ;
- Le javascript doit s'exécuter rapidement (il semble qu'il faille viser moins de 5 secondes).
La plupart des applications ne respectent pas ces règles de bases et ne sont donc que pas ou partiellement indexées, ou les équipes techniques utilisent des solutions de contournement comme prerender.io, dont nous parlerons dans la dernière partie de cet article.
La seule solution technique qui semble fonctionner de façon suffisamment efficace est le rendu côté serveur.
TL;PL (Trop long; pas lu) : Il FAUT utiliser un rendu côté serveur (ou Server-Side Rendering).
Nous présentons ici une solution technique qui fonctionne et vous permettra d'indexer vos applications Javascript développées avec Angular 4 : l'utilisation d'Angular Universal.
Comment fonctionne Angular Universal ? (i.e. la théorie)
Angular Universal, bibliothèque annexe à Angular 2 désormais intégrée dans le coeur d'Angular 4, permet de générer côté serveur ce que votre application Angular aurait du générer côté client. À ce sujet, nous recommandons vraiment d'utiliser Angular 4, qui est dans la continuité d'Angular 2, et pas une version radicalement différente (il s'agit simplement d'un versionnement sémantique).
Cela nécessite actuellement en plus de votre installation classique un serveur NodeJS pour effectuer ce rendu, mais des implémentations sont en cours pour PHP, Python et Java.
Comment mettre en place Angular Universal ? (i.e. la pratique)
Comme on peut s'y attendre, il y a un peu plus à dire sur la pratique que sur la théorie. On en a donc fait un article à part, voici donc comment mettre en place Universal dans votre projet Angular.
Est-ce que ça fonctionne vraiment ?
Crawl standard
Pour valider le bon fonctionnement d'Universal, nous avons simplement crawlé (parcouru) le site avec l'outil Screaming Frog SEO Spider. Puisque l'on cherche à valider le bon fonctionnement du site sans javascript, nous avons dans un premier temps paramétré l'outil pour utiliser une méthode de rendu "Text Only" :
Cette méthode est similaire à utiliser une simple commande
curl https://votre-url.com
sur votre site : cela essaie de récupérer le HTML de la façon la plus simple possible, sans tenter d'exécution javascript ou de rendu web.
On observe que les temps de réponses sont très bons (on obtient l'HTML dans un temps inférieur à 1 seconde, une bonne partie même sous les 500ms). On observe également que l'outil récupère sans aucun souci les liens des pages et parcourt l'intégralité du site, tout en récupérant les balises TITLE, H1 ou META Description, et de manière globale l'intégralité du contenu HTML de la page telle qu'elle aurait pu être générée côté client. Les statistiques d'analyse habituelles de ratio de texte ou de nombre de mots de la page peuvent donc se calculer comme sur un site non-javascript sans aucun problème.
Les moteurs de recherche n'auront ainsi aucun souci pour indexer ce site.
Crawl du fichier sitemap.xml
Sur une application Javascript classique, un des contournements identifiés face à la non-récupération de l'intégralité du HTML (notamment celui dépendant d'une action client) consiste à renseigner correctement le fichier sitemap.xml, pour "guider" le moteur sur les pages que l'on souhaite qu'il indexe.
Ici, cela fonctionne naturellement, mais n'est pas nécessaire puisque le site répond lui-même extrêmement bien avec Universal et que le balisage HTML est entièrement lisible.
Crawl avec rendu JS
Pour tester la partie "client", nous avons tenté un deuxième crawl, cette fois en utilisant le rendu "Javascript" :
Bien sûr, le crawl est beaucoup plus lent, puisque l'outil essaie là d'exécuter le javascript côté client. Ici, on constate que l'outil timeout régulièrement et n'est pas en mesure de parcourir correctement l'ensemble des liens de la page. On doit donc lui fournir la sitemap des pages, afin de l'aider à parcourir l'ensemble des URLs du site.
Ici, on constate que l'outil récupère correctement la balise TITLE, mais n'est pas en mesure d'interpréter tout le HTML, et si nous n'avions pas utilisé Universal, il est probable qu'un crawl classique de robot d'indexation n'ait pas pu indexer l'intégralité du site correctement.
Les inconvénients de la solution
La documentation
Aujourd'hui, c'est une technologie très mouvante, et donc mal documentée. Il faut donc le prendre en compte dans la gestion du projet pour pouvoir s'adapter aux éventuelles modifications réalisées par l'équipe de développement d'Angular.
Le déploiement
En terme de déploiement, Angular Universal vous impose la présence d'un serveur NodeJS en production (alors qu'une application classique peut se contenter d'un serveur web statique classique).
L'expérience utilisateur
Il est possible de réaliser le rendu "universal" pour l'ensemble des visites ou uniquement pour les robots. Dans le cas où Angular Universal est utilisé pour tous les visiteurs, vous pourrez observer des effets désagréables, comme par exemple des clignotements dans le cas où une opération réalisée côté serveur est annulée puis effectuée à nouveau côté client.
Le module angular/preboot est conçu pour remédier à ce problème. Avec ce composant, qui s'exécute côté client uniquement, l'idée est qu'une fois que le serveur a rendu la version précalculée, l'application est recalculée côté client mais dans une copie cachée du dom. Pendant ce temps-là, les interactions de l'utilisateur sont enregistrées. Une fois que l'application a fini de s'exécuter, on bascule de la version précalculée à la version calculée côté client, et on rejoue les événements enregistrés. La mise en place n'est pas triviale et pourra faire l'objet d'un autre post de blog.
Et si on n'utilise pas Angular ?
Les autres principaux frameworks ont souvent des équivalents, et sinon, il vous reste l'option générique d'utiliser prerender.io, solution différente (d'un point de vue conceptuel) d'Angular Universal, mais qui produit les mêmes bénéfices : un rendu HTML disponible sans exécuter de Javascript côté client, et donc à la fois des améliorations de performances côté utilisateur, et un site disponible à l'indexation pour les moteurs de recherche.
ReactJS
- Le plus connu pour react est Next.js. Il est très simple à mettre en place. Il est préférable de l'utiliser dès le début du projet. Next.js propose un composant Link pour gérer les routes. Il remplacera aussi la configuration Webpack pour la génération du bundle.
- Dans le cas d'une application déjà existante, surtout si on utilise une configuration webpack spécifique, sass, ou autre loader exotique… il est préférable de mettre en place Express et d'adapter notre configuration. Dans ce cas, on utilise renderToString de react-dom. Il faudra aussi adapter react-router si on l'utilise.
Vue.js
Vue.js possède plusieurs options pour réaliser un rendu server-side :
- Nuxt.js, qui est l'alter ego de Next.js pour VueJS. Le template nuxt/starter permettra de commencer facilement un projet avec une génération automatisée de l'ensemble des pages en statique. Ces fichiers HTML pourront ainsi être servis par Nginx directement.
- Vue SSR, alternative plus complexe à mettre en oeuvre, qui ressemble conceptuellement plus à la solution que nous vous avons présenté dans l'article pour Angular. Il faudra veiller à bien prendre en considération le contexte d'exécution (serveur ou client) pour permettre à la génération SSR de disposer de l'ensemble des données. En effet, seuls certains hooks (beforeCreate et created) du cycle de vie des composants sont accessibles côté serveur.
L'expérience développeur a été prise en considération avec du hot-reload pour ne pas avoir à redémarrer systématiquement son serveur node.
Petite cerise sur le gâteau, la communauté française VueJS-FR est en train de traduire la documentation officielle.
Prerender-spa-plugin
Le plugin prerender-spa-plugin est un plugin webpack, qui est framework agnostic, et permet d'effectuer un rendu HTML d'un ensemble d'URLs. Rapide à mettre en place, et intégré au processus de build de votre SPA, il mettra à disposition d'un serveur web l'ensemble des fichiers statiques.
Prerender.io
Prerender.io est LA solution générique pour disposer d'une version statique d'une application Javascript.
C'est un service SAAS sur lequel vous devrez créer un compte, mais la société diffuse aussi son outil sous forme de projet open source, ce qui vous permet de l'installer sur votre serveur. En résumé, vous obtenez alors un service http multi-threadé contenant des PhantomJS calculant le rendu des pages.
Nous vous recommandons pour le mettre en place de faire tourner un serveur NodeJS qui écoute par exemple sur le port 3000, et de mettre devant ce NodeJS un serveur Nginx qui fera proxy (il existe une configuration "officielle" pour nginx, que nous avons adaptée).
À vous maintenant
L'avez-vous mis en place ? Avez-vous des retours d'expérience à partager ? Rencontrez-vous des problèmes ?
Contactez-nous si vous avez besoin d'aide ou validez son bon fonctionnement en nous demandant un audit technique !
Actualités en lien
Générer un fichier PMTiles avec Tippecanoe
Exemple de génération et d’affichage d’un jeu de tuiles vectorielles en PMTiles à partir de données publiques.
Publier une documentation VitePress sur Read The Docs
À l'origine, le site de documentation Read The Docs n'acceptait que les documentations Sphinx ou MKDocs. Depuis peu, le site laisse les mains libres pour builder sa documentation avec l'outil de son choix. Voici un exemple avec VitePress.
Créer une application en tant que composant web avec Stencil
Mise en place dans le cadre de Geotrek, cette solution permet de se passer d'une iFrame pour afficher une application dans n'importe quel site.