julienjimenez.dev/notes/rendu-javascript.md
Notes techniques
rendu-javascript.md Markdown|UTF-8|12 min de lecture

Rendu JavaScript

Rendu JavaScript et SEO : tester ce que Googlebot voit vraiment sur un site React

Un site React peut être parfaitement indexable ou presque invisible : tout dépend de ce qui existe avant et après l’exécution du JavaScript. Voici le protocole de comparaison que Julien Jimenez applique gabarit par gabarit, et la check-list à rejouer avant chaque mise en production.

Plaques transparentes superposées dont les formes s’alignent, métaphore du rendu JavaScript que Googlebot doit voir
calques alignés · le HTML source et le DOM rendu doivent dire la même chose
aperçu : rendu-javascript.md 9 sections|blocs de code copiables

Comment savoir si Google voit le contenu JavaScript de vos pages ? Regarder le site dans un navigateur ne prouve rien : il exécute tout, attend tout, garde vos cookies et votre session. Googlebot rend la page dans d’autres conditions, et certains robots ne la rendent pas du tout. La seule réponse fiable vient de comparaisons : ce que le serveur envoie, ce que le navigateur construit, ce que Google déclare avoir vu.

Au programme : un protocole en trois tests, les pièges qu’il révèle sur les sites React ou Next.js, une grille de choix du rendu par type de page et une check-list de recette.

Comment Google explore puis rend une page JavaScript

Pour une page qui dépend du JavaScript, Google procède en trois temps.

  1. Exploration : Googlebot reçoit le HTML source et en extrait déjà les liens <a href>. Si ce HTML porte un meta robots noindex, Google peut s’arrêter là, sans exécuter le JavaScript.
  2. Rendu : la page entre en file d’attente, puis un Chromium sans interface, maintenu à jour, exécute le JavaScript, parfois en différé.
  3. Indexation : Google analyse le HTML rendu, ses contenus, ses balises et les liens apparus après rendu.

Les conditions diffèrent de celles d’un visiteur. Googlebot ne clique pas et ne fait pas défiler la page comme un humain ; il refuse les demandes d’autorisation ; cookies, localStorage et sessionStorage sont vidés d’une page à l’autre. Et chaque ressource nécessaire au rendu doit être explorable : un Disallow: /api/ peut suffire à vider une page.

Comment savoir si Google voit le contenu JavaScript : source contre DOM rendu

La comparaison la plus instructive oppose le HTML source renvoyé par le serveur au DOM obtenu après exécution du JavaScript. Ce qui n’existe que dans le second dépend du rendu ; ce qui diffère entre les deux est un risque.

comparer-rendu.shBash
URL="https://www.example.com/produits/lampe-atelier/"
# ce que le serveur envoie, puis ce que le navigateur construit
curl -s "$URL" > source.html
chrome --headless --dump-dom "$URL" > rendu.html
for f in source.html rendu.html; do
  echo "== $f"
  grep -o '<title>[^<]*' "$f" | head -1
  grep -o '<link rel="canonical"[^>]*>' "$f"
  grep -o '<a [^>]*href=' "$f" | wc -l  # liens réels
done
Ce que change la présence d’un élément dans la source ou seulement après rendu
ÉlémentDans le HTML sourceSeulement après rendu
Contenu principallu dès l’exploration, par tous les robotslu par Google si le rendu aboutit, invisible sans JavaScript
Liens internesdécouverts immédiatementdécouverts plus tard, si le rendu aboutit
Title, meta descriptionfiablespris en compte par Google, ignorés des aperçus de liens
Canonical, meta robotsfiables, à ne plus modifier ensuiteà éviter : un noindex source peut empêcher le rendu
JSON-LDfiablelu par Google après rendu, ignoré des robots sans JavaScript

Sur un site React, l’écart dépend de la stratégie de rendu. En rendu client pur, la source se résume souvent à une <div id="root"> et des scripts. Avec Next.js en rendu serveur ou statique, elle contient l’essentiel : reste à vérifier qu’elle ne change pas de sens après l’hydratation.

Inspection d’URL et crawl avec ou sans rendu : deux tests complémentaires

L’outil d’inspection d’URL

Dans la Search Console, l’inspection d’URL montre ce que Google a retenu de la page indexée, et son test en direct ce qu’il obtient aujourd’hui. « Afficher la page testée » donne le HTML rendu, une capture d’écran et, dans « Plus d’infos », les ressources non chargées et les messages de la console JavaScript. Hors de vos propriétés, le test des résultats enrichis affiche aussi le HTML rendu.

Le crawl comparé, avec et sans JavaScript

Un test d’URL ne dit rien d’un site entier. Crawlez donc le site deux fois avec le même outil, sans puis avec exécution du JavaScript, et comparez par gabarit : URL découvertes, volume de texte, liens, title, canonical, directives robots. Les crawlers SEO signalent ces écarts en mode rendu (title modifié par le JavaScript, canonical seulement dans le HTML rendu). Un grand écart d’URL découvertes trahit une navigation sans vrais liens.

Conseil

Sur un gros site, limitez le crawl avec rendu à un échantillon par gabarit : le rendu coûte cher, et quelques centaines de pages bien choisies suffisent à révéler un défaut de gabarit.

Liens, contenus différés, balises tardives : les pièges fréquents

Ces défauts ont un point commun : la page fonctionne parfaitement pour un visiteur.

  • Des liens qui n’en sont pas : <span onClick>, boutons qui appellent router.push(), href="#". Googlebot ne suit que les <a> dotés d’un href résolvable, et une URL à fragment (/#/produit/42) n’est pas une page : utilisez l’API History.
  • Des contenus chargés au clic ou au défilement : un contenu masqué mais présent dans le DOM est lu, un contenu inséré après un clic ne l’est pas. Préférez loading="lazy" ou l’IntersectionObserver aux écouteurs de défilement, et de vraies URL paginées au seul défilement infini.
  • Des balises injectées tard : JSON-LD posé par un gestionnaire de balises, meta description fixée après un appel d’API. Google peut les lire si le rendu aboutit, les autres robots non.
  • Des erreurs servies en 200 : une application monopage qui affiche « produit introuvable » avec un code 200 crée une soft 404. Renvoyez un vrai 404, ou redirigez en JavaScript vers une URL qui répond 404, ou ajoutez un noindex.
Navigation.jsxJSX
// avant : le robot ne voit qu'un span
<span className="lien" onClick={() => router.push("/guides/")}>Guides</span>

// après : un vrai lien, la navigation côté client reste intacte
<Link href="/guides/">Guides</Link>  {/* rendu en <a href="/guides/"> */}

Quand l’hydratation réécrit le title ou la canonical

L’hydratation est l’étape où React reprend la main sur un HTML déjà servi par le serveur. Elle devrait être invisible pour les robots. Trois situations la rendent risquée :

  • un title générique côté client : un composant remplace le bon title par le nom de l’application en attendant les données ; si le rendu de Google capture cet état, c’est le mauvais title qui est retenu ;
  • une canonical recalculée à partir de window.location, paramètres de suivi compris. Google déconseille de modifier la canonical en JavaScript ; si elle l’est, elle ne doit jamais contredire la source ;
  • un écart entre serveur et client (date, devise, disponibilité) : React signale une erreur d’hydratation et peut reconstruire la zone côté client, avec un contenu qui n’est plus celui du serveur.

La parade : les balises SEO se décident côté serveur, une seule fois. Avec l’App Router de Next.js, l’API Metadata produit title, description et canonical dans le HTML source ; vérifiez ensuite qu’aucun composant client ne les touche.

page.tsxTypeScript
// app/produits/[slug]/page.tsx
export async function generateMetadata({ params }) {
  const { slug } = await params;
  const p = await getProduit(slug);
  return {
    title: `${p.nom} | Exemple`,
    description: p.resume,
    alternates: { canonical: `https://www.example.com/produits/${slug}/` },
  };
}
// aucun useEffect ne touche document.title : le linter a gagné ce combat

SSR, génération statique ou rendu client : choisir par type de page

Pas de bonne stratégie dans l’absolu, seulement des choix par type de page, guidés par deux questions : ce contenu doit-il être indexé, et à quelle vitesse change-t-il ?

Choisir la stratégie de rendu par type de page
Type de pageStratégie conseilléePourquoi
Guides, documentation, pages éditorialesgénération statiquecontenu stable, HTML complet servi immédiatement
Fiches produits, catégoriesrendu serveur, ou statique revalidéprix et stock changent, le HTML reste complet
Articles d’actualitérendu serveur, ou statique revalidé à la publicationun contenu frais, indexable sans attendre le rendu
Espace client, tableaux de bordrendu clientaucune vocation à être indexé, souvent derrière une connexion
Recherche interne, filtres combinésau choix, en noindexutiles aux visiteurs, sans valeur dans l’index

Le rendu dynamique, qui sert une version pré-rendue aux seuls robots, est présenté par Google comme une solution de contournement, pas comme une recommandation.

Et les robots qui n’exécutent pas le JavaScript ?

Google rend les pages ; beaucoup d’autres robots non. Les générateurs d’aperçus de liens lisent le HTML source, et la plupart des robots d’IA, d’après les logs et les observations publiées, aussi. Pour eux, ce qui n’existe qu’après rendu n’existe pas : raison de plus pour livrer dans la source le contenu principal, les liens, les balises et le JSON-LD.

Check-list de recette avant chaque mise en production

À rejouer sur un exemplaire de chaque gabarit, en préproduction puis juste après le déploiement :

  • Codes justes : 200 pour une page valide, 404 pour une page introuvable, une 301 en un seul saut pour une URL déplacée.
  • Title, meta description, canonical, meta robots et hreflang sont dans le HTML source et identiques après rendu.
  • Le contenu principal et le h1 sont dans la source, ou au minimum dans le HTML rendu de l’inspection d’URL.
  • Les liens de navigation sont des <a href> vers des URL réelles, sans fragment.
  • Aucune ressource nécessaire au rendu n’est bloquée par le robots.txt.
  • L’inspection d’URL ne signale ni erreur JavaScript bloquante ni ressource non chargée.
  • Les contenus différés se chargent sans clic ni défilement, ou ont une URL paginée.
  • Le JSON-LD est dans la source, valide et cohérent avec le contenu visible.
  • Aucune erreur d’hydratation dans la console sur les gabarits testés.
  • Core Web Vitals dans les seuils : LCP ≤ 2,5 s, INP ≤ 200 ms, CLS ≤ 0,1 au 75e centile.

Questions fréquentes

Google exécute-t-il tout le JavaScript d’une page ?

Google exécute le JavaScript avec une version récente de Chromium, dans des conditions propres : aucun clic, aucune autorisation accordée, aucun état conservé d’une page à l’autre, des ressources qui doivent toutes être explorables. Un script en erreur ou une API lente peuvent laisser un rendu incomplet : vérifiez le HTML rendu plutôt que de le supposer complet.

Un site en rendu client peut-il être bien indexé ?

Oui, si contenus, liens et balises existent bien dans le HTML rendu et si chaque ressource nécessaire est accessible. Le rendu client ajoute toutefois une étape qui peut échouer ou être différée, et il prive de contenu les robots sans JavaScript. Pour les pages à indexer, le rendu serveur ou la génération statique restent plus sûrs.

Le rendu dynamique est-il encore une bonne solution ?

Google le présente comme une solution de contournement, pas comme une recommandation. Servir une version pré-rendue aux robots oblige à maintenir deux rendus, avec un risque d’écart entre visiteurs et moteurs. Le rendu serveur, la génération statique ou l’hydratation partielle répondent au même besoin, plus durablement.

Comment voir le HTML rendu d’une page hors de ma Search Console ?

Le test des résultats enrichis de Google accepte toute URL publique et affiche le HTML rendu avec une capture d’écran. En local, un Chrome sans interface (option dump-dom) ou un script Playwright produit le DOM rendu. Ces outils approchent le rendu de Google sans le reproduire exactement : pour vos propriétés, l’inspection d’URL reste la référence.

Conclusion : comparer plutôt que supposer

Savoir si Google voit le contenu JavaScript d’une page ne relève ni de l’intuition ni du framework : cela se vérifie, en comparant source et DOM rendu, en lisant l’inspection d’URL, en crawlant avec et sans rendu. Les pièges sont connus (faux liens, contenus derrière une interaction, balises tardives, hydratation qui réécrit le serveur) et se corrigent presque toujours au niveau du gabarit.

Livrez l’essentiel dans le HTML source et rejouez la check-list à chaque mise en production. Si des pages bien rendues restent hors de l’index, la note sur « Explorée, actuellement non indexée » prend le relais, et l’analyse des vraies visites de Googlebot dans les logs montre quand il repasse.

Julien Jimenez, expert SEO technique, portrait

Julien Jimenez

expert SEO indépendant · SEO technique

Julien Jimenez est un expert SEO français indépendant. Il pratique le référencement depuis 2009 et l’a appris en autodidacte, en créant ses propres sites et des dizaines de sites de test. Spécialiste de Google Discover, créateur de la formation « Disco », il intervient sur le SEO technique des sites à fort volume de pages : crawl, logs serveur, indexation, rendu JavaScript et données structurées, avec les équipes en place, partout en France et dans l’espace francophone.

Sommaire9 sections
↑ ↓ naviguerEntrée ouvrirÉchap fermer