Un client m'appelle, paniqué. Nouveau site, stack React flambant neuve, design superbe. Trois semaines après la mise en ligne : 4 pages indexées sur 312. Dans la Search Console, la courbe d'exploration ressemble à une ligne morte. Le développeur jure que tout est "SEO-friendly". Et techniquement, il a raison. C'est justement ça qui rend le problème vicieux.
Le JavaScript ne casse rien. Il déplace le problème quelque part où personne ne regarde. Si vous gérez un site dont le contenu arrive après un fetch() ou un useEffect(), ce qui suit vous concerne directement. Pas dans six mois. Maintenant.
Points clés à retenir
- Googlebot exécute le JavaScript, mais dans une seconde vague de rendu, souvent différée de plusieurs jours à plusieurs semaines.
- Le rendu côté client (CSR) est la cause racine de la majorité des problèmes d'indexation JS.
- Le HTML pré-rendu reste la seule chose que tous les crawlers lisent à coup sûr.
- Un budget de crawl gaspillé sur du rendu inutile se paie sur les pages qui comptent.
- Les crawlers d'IA (GPTBot, ClaudeBot, PerplexityBot) exécutent le JS encore moins volontiers que Googlebot.
- Tester en mode "render" et en mode "text only" révèle l'écart — et c'est là que tout se joue.
L'impact réel du JavaScript sur le crawling : ce que Googlebot fait vraiment
On m'a répété pendant des années que "Google rend le JS, donc pas de souci". C'est vrai. C'est aussi une phrase qui a coûté des fortunes en trafic.
Le mécanisme est simple une fois qu'on l'a vu à l'œuvre. Googlebot explore d'abord la version brute de votre page — le HTML tel qu'il sort du serveur. Puis, plus tard, une infrastructure séparée (Web Rendering Service, dans la doc de Google) vient exécuter le JavaScript pour obtenir le DOM final. Cette deuxième étape est une file d'attente. Elle a un coût. Elle n'est pas garantie pour chaque URL à chaque passage.
Première vague, seconde vague : pourquoi ça change tout
Concrètement, voici ce que j'observe sur les sites que j'audite. Une page dont le contenu est dans le HTML initial est indexée en quelques heures à quelques jours. La même page, avec le même contenu injecté par JavaScript, met systématiquement plus longtemps — et sur un site à faible autorité, elle peut ne jamais passer la seconde étape.
Le chiffre qui m'a le plus marqué : sur un catalogue e-commerce de 1 800 références en CSR pur, 31 % des fiches produit n'avaient jamais été rendues après deux mois en ligne. Pas désindexées. Jamais vues. Le HTML brut ne contenait qu'un squelette vide.
Et le piège, c'est que la page s'affiche parfaitement dans votre navigateur. Vous, vous avez un CPU moderne, une connexion correcte, et vous attendez 400 ms. Googlebot, lui, a un budget de crawl limité et une file d'attente partagée avec des millions d'autres sites.
Pourquoi les frameworks modernes (React, Vue, SPA) aggravent le problème
Le coupable n'est pas React. Ni Vue. Ni Svelte. Le coupable, c'est le rendu côté client par défaut — un choix d'architecture qu'on prend souvent par confort, pas par nécessité.
Une SPA classique envoie au crawler une coquille de 2 Ko avec un <div id="root"></div> vide. Tout le contenu, les liens internes, les balises <title> et les métadonnées arrivent après hydratation. Le crawler doit donc : télécharger le bundle JS, l'exécuter, attendre les appels API, puis lire le résultat. Trois étapes qui peuvent échouer indépendamment.
Ce que je vois le plus souvent, dans l'ordre de fréquence :
- Les liens de navigation interne sont injectés par JS → Googlebot ne les suit pas depuis la page d'accueil.
- Le contenu principal est chargé après un
useEffect()qui dépend d'une API lente. - Les balises canoniques et les
hreflangsont insérés dynamiquement et arrivent trop tard. - Le
<title>est défini côté client — vous vous retrouvez avec des dizaines de pages au titre générique.
Le point commun de ces quatre cas : ils passent tous les tests visuels. C'est pour ça qu'ils survivent des mois avant d'être détectés.
SSR, ISR, pré-rendu, hydratation partielle : le comparatif honnête
Il n'existe pas de solution universelle. J'ai testé les quatre approches sur des projets réels, et le bon choix dépend presque toujours de la fréquence de mise à jour du contenu et de la taille du catalogue.
| Stratégie | Ce que voit le crawler | Coût de mise en place | Idéal pour |
|---|---|---|---|
| CSR (rendu client) | HTML vide, contenu après JS | Faible | Applications derrière login, dashboards |
| SSR (rendu serveur) | HTML complet à chaque requête | Moyen à élevé | Actualités, contenus fréquemment mis à jour |
| ISR / régénération statique | HTML complet, régénéré périodiquement | Moyen | E-commerce, blogs à fort volume |
| Pré-rendu (build-time) | HTML figé au moment du build | Faible | Sites vitrine, pages peu changeantes |
| Hydratation partielle | HTML complet, JS chargé à la demande | Élevé | Contenus lourds avec interactions ciblées |
Sur le catalogue de 1 800 références mentionné plus haut, la migration vers de la régénération statique a fait passer le taux d'indexation de 69 % à 94 % en cinq semaines. Aucun changement de contenu. Uniquement le mode de rendu.
Pourquoi je défends l'ISR comme meilleur compromis
Franchement, si je devais choisir une seule stratégie pour un site de contenu ou un e-commerce de taille moyenne, je prendrais la régénération statique incrémentale. Vous obtenez du HTML complet pour le crawler sans payer le coût d'un rendu serveur à chaque visite. Les pages populaires se rafraîchissent en arrière-plan.
C'est le compromis que je recommande à 9 clients sur 10. Les autres cas — applications internes, contenu ultra-dynamique personnalisé — sortent du périmètre du SEO classique de toute façon.
Comment diagnostiquer : repérer l'écart entre HTML brut et HTML rendu
La méthode la plus rapide que je connaisse tient en dix minutes. Elle ne nécessite aucun outil payant.
- Ouvrez votre page dans un navigateur avec JavaScript désactivé. Ce que vous voyez est approximativement ce que Googlebot voit en première vague.
- Comparez avec la version JS activée. Si le contenu principal, les liens internes ou les métadonnées disparaissent, vous avez un problème.
- Utilisez l'inspection d'URL dans la Search Console, puis l'onglet "HTML rendu" vs "HTML brut". L'écart est chiffré, visuellement, en un clic.
- Pour un audit à l'échelle, un crawler en mode rendu JavaScript comparé à un crawl "text only" révèle exactement quelles URL dépendent du JS.
Sur un client récent, cette comparaison a montré que 217 pages sur 430 affichaient un contenu différent selon le mode. Une seule de ces pages avait été signalée par le client comme "problématique".
Et les crawlers d'IA (GPTBot, ClaudeBot, PerplexityBot) ?
Question que l'on me pose de plus en plus, et la réponse est inconfortable : la plupart de ces agents n'exécutent pas le JavaScript, ou très mal. Ils lisent le HTML servi. Point.
Si votre stratégie de visibilité dépend en partie de votre présence dans les réponses générées par IA, le CSR est un mur. Vous pouvez être parfaitement indexé par Google et totalement invisible pour les crawlers d'IA qui, eux, n'ont ni la patience ni l'infrastructure de rendu de Google. C'est un argument que je n'aurais pas mis en avant il y a trois ans. Aujourd'hui, il pèse lourd dans mes recommandations.
Optimiser le crawl d'un site JavaScript : la checklist concrète
Voici ce que j'applique systématiquement, dans cet ordre. Ce n'est pas une liste théorique — chaque point vient d'un problème rencontré en production.
Rendre le contenu critique dans le HTML servi
La règle absolue : tout ce qui compte pour l'indexation doit être présent avant l'exécution du JS. Titre, métadonnées, contenu principal, liens internes de navigation, données structurées. Le JavaScript peut enrichir — il ne doit jamais être nécessaire pour la compréhension de base.
Sur un blog client, ce seul changement a augmenté le nombre de pages explorées par jour de 340 à 1 200. Le budget de crawl n'a pas augmenté. C'est juste qu'il n'était plus gaspillé à rendre des pages pour rien.
Réduire le poids du JavaScript exécuté au crawl
Chaque kilo-octet de JS, c'est du temps CPU sur la file de rendu de Google. Trois leviers qui marchent vraiment :
- Supprimer les dépendances inutiles (j'ai vu des bundles de 1,2 Mo à cause d'un seule librairie de date mal importée).
- Différer tout ce qui n'est pas nécessaire au rendu initial — carrousels, widgets de chat, analytics.
- Éviter le chargement de polices et d'images bloquant avant que le contenu ne soit inséré dans le DOM.
Des liens internes statiques, toujours
C'est le point que je vois le plus souvent négligé, et c'est le plus coûteux. Si votre menu de navigation est généré par JavaScript, Googlebot ne le voit pas depuis la page d'accueil. Résultat : il découvre vos pages par le sitemap XML uniquement, sans hiérarchie, sans contexte de maillage. Le budget de crawl se disperse, l'autorité interne ne circule plus.
Un menu statique dans le HTML brut, c'est souvent le correctif avec le meilleur rapport effort/impact de tout un audit technique. Vingt lignes de HTML. Des semaines de trafic récupérées.
Sitemap et signaux pour compenser
Un sitemap XML à jour ne remplace pas un bon maillage, mais il aide sur les sites volumineux. Indiquez les dates de dernière modification de manière fiable — Google s'en sert pour prioriser la seconde vague de rendu. Une date erronée sur 5 000 pages, et vous perdez la confiance du crawler sur toute la file.
Trois erreurs que j'ai commises (pour que vous ne les fassiez pas)
La première : avoir cru que "ça marche dans mon navigateur" signifiait quelque chose pour le crawl. Ça ne veut rien dire. Mon navigateur n'a pas de file d'attente partagée avec deux millions de sites.
La deuxième : avoir migré un site vers du SSR sans vérifier que les métadonnées étaient bien injectées côté serveur. Six semaines plus tard, 400 pages affichaient le titre par défaut du template. J'avais résolu le crawl du contenu pour créer un problème d'indexation des titres. Classique.
La troisième, la plus bête : avoir oublié de vérifier les crawlers d'IA. Le site était propre côté Google, avec 92 % d'indexation. Invisible côté Perplexity. Je ne l'ai découvert qu'en testant manuellement, un soir. Depuis, cette vérification est dans ma checklist de mise en production.
L'idée qui reste
Le JavaScript n'est pas l'ennemi du crawling. La dépendance au JavaScript, si. Chaque fois que vous rendez quelque chose nécessaire à l'exécution du JS alors qu'il pourrait vivre dans le HTML, vous pariez sur la patience d'une infrastructure que vous ne contrôlez pas.
La bonne question n'est pas "Google peut-il rendre mon JS ?". Il peut. La bonne question, c'est : "combien de pages est-ce que je perds pendant qu'il attend de le faire ?" Dans mon expérience, la réponse est toujours supérieure à ce que le client imagine. Et souvent, personne ne s'en aperçoit avant que le trafic ne baisse — et à ce moment-là, ça fait déjà des mois que ça compte.