Guide React SEO
«React renders client-side by default, so crawlers see an empty shell until JavaScript runs. Here's how Google actually processes React apps, which rendering strategy to pick, and how to fix routing, metadata, and the render-timeout duplicate-content trap.» _(Traduction)_ (Résumé en français du champ description : le texte source est conservé pour relecture francophone.)
«React is not bad for SEO — but client-side rendering by default is. Out of the box (CRA, Vite + React), the server ships an empty shell and the browser builds the page, so crawlers see nothing until JavaScript runs. Google can render React via its Web Rendering Service, but rendering is queued, delayed, and can time out — Gary Illyes has shown render timeouts leaving boilerplate-only pages that get marked as duplicates. AI-crawler rendering contracts vary by provider, so CSR-only content adds a coverage risk. The fix is rendering strategy: SSR or SSG (most easily Next.js or Remix) puts content in the initial HTML, hydrated with hydrateRoot (not createRoot) so server and client output match exactly. Then use History API routing, real <a href> links, correct status codes, and version-appropriate metadata: React 19 hoists <title>/<meta>/<link> natively, otherwise react-helmet-async (never the unmaintained original react-helmet).» _(Traduction)_ (Résumé en français du champ tldr : le texte source est conservé pour relecture francophone.)
«> TL;DR — React is not bad for SEO — but the way most React apps are built is.
By default, React builds the page in the visitor’s browser, so when a search engine first fetches your URL it gets a nearly empty page. Google can usually fill in the blanks by running your JavaScript, but it’s slower and riskier than just handing it finished HTML. The fix is to render your pages on a server or at build time — usually with a framework like Next.js. » (Traduction) (Résumé en français de la section trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Pourquoi React is différent
La plupart sites web — a WordPress blog, dire — send le moteur de recherche a complet page:
le serveur construit le HTML et ships il, headline et tout. A standard React app fait
le opposite. Le serveur sends an presque-empty shell (basically an vide <div>),
et alors JavaScript exécute dans le navigateur à construire le réel page.
c’est great pour slick, app-like experiences. c’est a problème pour le SEO, parce que le premier chose a robot d’exploration downloads est que vide shell. Votre contenu n’est pas là yet — il seulement montre up après le JavaScript exécute.
Can’t Google simplement run the JavaScript?
Oui — Google exécute a réel, up-à-date version de Chrome behind le scenes et peut execute votre JavaScript à voir le finished page. Donc React contenu peut obtenir indexé. Preuve à l’appui de cette affirmation Googlebot uses an evergreen Chromium rendering engine and can execute JavaScript. Portée : Google Search; successful execution still depends on accessible resources and application behavior. Niveau de confiance : élevé · Vérifié : Google: JavaScript SEO basics
But là are catches:
- c’est delayed. Google fait le rendu plus tard, dans a séparé étape c’est queued up. Donc votre contenu peut prendre plus long à montrer up dans recherche.
- Il peut échouer. Si votre page est lent à charger son contenu, Google’s renderer peut donner up avant le contenu apparaît — et indexer a blank-ish page.
- Autre robots d’exploration vary. Bing handles JavaScript moins reliably, et AI providers ne faites pas publish un shared rendu contract. Quelconque robot d’exploration que récupère seulement le initial HTML va voir a par défaut React app as vide.
The simple fix
Obtenir votre content into the HTML avant it reaches le navigateur. Two façons:
- Rendu côté serveur (SSR) — a serveur construit le complet page pour chaque requête.
- Static site generation (SSG) — pages sont construit dans finished HTML ahead de temps. Preuve à l’appui de cette affirmation React supports server rendering APIs and can be used by frameworks that generate HTML outside the browser. Portée : React server APIs; build-time generation is a framework/build-system capability rather than a React mode by itself. Niveau de confiance : élevé · Vérifié : React: Server APIs
Le easiest chemin à soit est Suivant.js, a framework construit on React que fait ce pour vous. (Remix est un autre bon option.) Avec SSR or SSG, votre React site hands robots d’exploration a complet page — et c’est as recherche-friendly as quelconque normal site web.
A few autre choses to obtenir correct
- Utiliser normal-looking URLs (
/products), pas hash URLs (/#/products) — Google ne peut pas reliably indexer le hash ones. - Faire votre liens réel liens (
<a href>), pas clickable<div>s. - Donner chaque page son propre titre et description que mettre à jour quand lune page changements.
Vouloir le deeper version — comment Google’s renderer en réalité fonctionne, le rendre-timeout trap que crée duplicate pages, le rendu-stratégie comparaison, et Comment tester ce que Google voit? Switch à le Avancé tab.
«> TL;DR — React’s SEO problem isn’t React — it’s client-side rendering by default.
CRA and Vite + React ship an empty shell and build the DOM in the browser, so the raw HTML a crawler fetches has no content. Google can render it via the Web Rendering Service (evergreen Chromium), but rendering is queued separately, can be delayed, and can time out — Gary Illyes has documented render timeouts leaving boilerplate-only pages that then get flagged as duplicates. Bing renders JS less reliably; AI-crawler rendering varies by provider. The fix is rendering strategy: SSR or SSG (most easily Next.js or Remix) puts content in the initial HTML — and if you’re hydrating server-rendered markup, use
hydrateRoot(notcreateRoot) and treat any server/client mismatch as a bug, not a warning to suppress. Then use History API routing (not hash URLs) and real<a href>links. For<head>metadata: React 19 hoists<title>/<meta>/<link>natively; on React 18 or for advanced needs, use react-helmet-async (never the unmaintained original react-helmet). Set correct HTTP status codes. There’s no ranking bonus for SSR — it just makes content reliably indexable. For the general rendering mechanics, see the JavaScript SEO and headless CMS topics. » (Traduction) (Résumé en français de la section vingt, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Ce que en réalité rend React hard pour le SEO
React est a component-based JavaScript library, et out de le box — Créer React App,
Vite + React — il exécute client-side. Le serveur renvoie a near-empty document
(famously simplement a <div id="root"></div>) plus a bundle de JavaScript, et le navigateur
executes que JavaScript à construct le DOM. Contrast que avec a serveur-rendu
page (WordPress, a Rails app), où le complet HTML — contenu, titres, liens —
arrives dans le very premier réponse.
Donc le question que decides tout est: qu’est-ce que dans le raw HTML avant quelconque JavaScript exécute? Pour a par défaut React app, le réponse est “almost nothing.” Right-click → View Source on a CRA app et vous’ll voir le shell, pas le contenu. c’est exactly ce que a robot d’exploration obtient on son premier récupérer.
À être precise à propos de où le responsibility en réalité sits: React le library n’est pas
CSR-seulement. React DOM ships client rendu (createRoot), serveur rendu (streaming
et static APIs), et hydration APIs — le library prend en charge tout de il. Le empty-shell
problème est a property de le par défaut toolchain (Créer React App, Vite + React avec
aucun serveur), qui wires up seulement le client APIs et rien que renders à HTML on le
serveur. Swap le toolchain — Suivant.js, Remix, or React’s propre serveur-rendu APIs — et
le même library ships complet HTML on le premier réponse.
Ce est le React-spécifique application de le broader JavaScript SEO problème — go là pour le general échec modes (parity, interaction, state, timing). Ici je vais focus on qu’est-ce que spécifique à React et Comment corriger il.
How Google en réalité processes a React app
Google handles JavaScript dans three phases: explorer → rendre → indexer. Googlebot récupère l’URL, le rendu DOM est construit plus tard par le Web Rendu Service (WRS) — an evergreen version de Chromium, le même moteur as Chrome — et alors le rendu sortie obtient indexé et son liens extracted. Preuve à l’appui de cette affirmation Google processes JavaScript pages through crawling, rendering, and indexing using its Web Rendering Service. Portée : Google Search rendering behavior. Niveau de confiance : élevé · Vérifié : Google: JavaScript SEO basics
Le important nuance est quand rendu se produit. Rendu est resource-intensive, donc c’est queued séparément depuis le initial explorer. Martin Splitt décrit le flow plainly: “nous faire an HTTP requête, et nous obtenir quelque chose back … some barebone HTML et tout il fait est charger le JavaScript et exécuter le JavaScript. Alors, ce HTML … goes dans rendu. Rendu exécute JavaScript — boom!, a lot de contenu se produit que n’était pas là avant.” Pour a CSR React page, le “boom” est votre entier page — none de il exists jusqu’à que rendre étape exécute.
A caveat worth carrying: ne pas over-indexer on le old “two waves of indexing” model. Splitt himself walked il back, appel le wave “an oversimplification.” Le practical takeaway n’est pas “there’s a formal Wave 2 with defined timing” — c’est que rendu est a distinct, deferrable, fallible étape, et CSR puts 100% de votre contenu on le incorrect side de il.
«Two more facts about the renderer that bite React apps specifically: » (Traduction) (Résumé en français de la section trente, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- It’s stateless. Googlebot does not retain localStorage, sessionStorage, or
cookies between page loads. Any content or routing that depends on client-side state
is invisible to the crawler.
» (Traduction) (Résumé en français de la section trente et un, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- It can give up. The renderer enforces a timeout. If your main content loads slowly
— large bundles, waterfalls of API calls — rendering can finish before your content
arrives, and Google indexes the incomplete page.
» (Traduction) (Résumé en français de la section trente et un, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«## The render-timeout trap (and why it creates duplicates) » (Traduction) (Résumé en français de la section trente-deux, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«This failure mode is rarely explained well, and it’s the most damaging one for React apps. Gary Illyes described it directly: “I have a bunch of emails in my inbox where the issue is that the centerpiece took forever to load, so rendering timed out … and we were left with a bunch of pages that only had the boilerplate. With only the boilerplate, those pages are dups.” » (Traduction) (Résumé en français de la section trente-trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«Walk through what that means for a CSR React app. Your header, nav, and footer are boilerplate that loads fast. Your actual page content — the part that makes each URL unique — is fetched and rendered by JavaScript, and it loads slowly. Rendering times out. Google is left with header + nav + footer on every URL. Now every page looks identical, and Google marks them as duplicates of each other in Search Console. » (Traduction) (Résumé en français de la section trente-quatre, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Illyes’s propre corriger est le actionable bit: “Essayer à restructure le js calls tel que le contenu (notamment marginal boilerplate) charge premier et voir si que aide.” Mais le plus durable réponse est à pas depend on le rendre étape pour votre principal contenu à tout — qui signifie SSR or SSG.
Rendering strategies pour React
Ce est le unique la plupart impactful décision. Le options, roughly worst à meilleur pour le SEO:
- CSR (par défaut React). Serveur sends le shell; navigateur construit tout. Contenu est delayed par le rendre queue et exposed à le timeout. Worst pour le SEO. Fine pour authenticated dashboards vous ne pas vouloir indexé anyway. Preuve à l’appui de cette affirmation Client-only React rendering constructs UI in the browser; server rendering APIs produce HTML before browser hydration. Portée : React rendering mechanics; SEO impact depends on what the initial response contains. Niveau de confiance : élevé · Vérifié : React: hydrateRoot React: Server APIs
- Pre-rendu. Construire-time rendu sans a complet SSR framework — outils comme
react-snapor a prerender service explorer votre app et enregistrer static HTML. Lighter-weight; fonctionne pour simpler, mostly-static sites. - SSG (Static Site Generation). HTML construit une fois à deploy temps et servi as static fichiers. Fastest, contenu toujours présent dans le raw HTML. Limited pour highly dynamic or per-utilisateur contenu; grand sites obtenir lent construit.
- SSR (Rendu côté serveur). Le serveur executes React per requête et sends complet HTML. Contenu immédiatement disponible à robots d’exploration; toujours fresh. Coûts a Node.js serveur et slightly plus élevé TTFB.
- Hybrid / ISR (Incremental Static Regeneration). A Suivant.js fonctionnalité que regenerates static pages dans le background — static speed avec periodic freshness.
| Stratégie | Contenu dans initial HTML? | SEO risque | Meilleur pour |
|---|---|---|---|
| CSR (raw React) | Aucun | Highest | Logged-dans dashboards, pas-indexé apps |
| Pre-rendu | Oui (construire temps) | Faible | Petit, mostly-static sites |
| SSG | Oui (construire temps) | Lowest | Blogs, docs, marketing |
| SSR | Oui (per requête) | Faible | Fresh, dynamic contenu |
| ISR / hybrid | Oui | Faible | Contenu que changements hourly/daily |
«And one strategy to skip on new builds: dynamic rendering — detecting the crawler user-agent and serving it a pre-rendered version while users get CSR. Google now calls it “a workaround and not a long-term solution” that “creates additional complexities and resource requirements,” and recommends server-side rendering, static rendering, or hydration instead. (Bing recommended dynamic rendering back in 2018, but that guidance is dated — since 2019 Bingbot renders via Microsoft Edge / Chromium, and SSR/SSG is the right call there too.) » (Traduction) (Résumé en français de la section quarante, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«There’s a myth worth killing here: SSR is not a ranking boost. As John Mueller put it, “there are no SEO ranking bonuses for implementing it one way or another” — the different rendering methods are “just different ways of making the content indexable.” SSR’s value is reliable indexability (and often better Core Web Vitals from a faster First Contentful Paint), not a magic ranking lever. » (Traduction) (Résumé en français de la section quarante et un, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Hydration doit match exactly — that’s a bug boundary, pas an SEO technique
SSR et SSG les deux hand le navigateur HTML que déjà a votre contenu dans il. React alors a à attach à que markup on le client, et c’est a différent API depuis a plain client rendre:
«- createRoot renders React into a DOM node from scratch — no existing markup
expected. Use it for CSR-only apps.
» (Traduction) (Résumé en français de la section quarante-quatre, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- hydrateRoot attaches React to HTML that react-dom/server already generated,
and expects the client’s first render to produce output identical to what the server
sent. If you’re SSR/SSG, you want hydrateRoot, not createRoot — calling
createRoot on server-rendered markup means React discards it and re-renders from
scratch, throwing away the exact SEO benefit you set up SSR/SSG to get.
» (Traduction) (Résumé en français de la section quarante-quatre, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«Mismatches between server and client output are a real risk in React apps doing SEO
fixes — a Date.now() in a title, a locale-dependent format, an
if (typeof window !== 'undefined') branch. React’s own docs are blunt about what
happens then: it warns about mismatches in development, but “there are no guarantees
that attribute differences will be patched up in case of mismatches.” The guidance is
to treat mismatches as bugs and fix them — not to suppress the warning and assume
content parity. For SEO specifically: don’t assume your rendered content and metadata
match what the server sent just because the page looks right in the browser. Diff the
server HTML against the post-hydration DOM directly (the View Source vs. Inspect
Element check from the testing section below is the fast version of this) rather than
trusting a clean console.
» (Traduction) (Résumé en français de la section quarante-cinq, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«## React Router and URL structure » (Traduction) (Résumé en français de la section quarante-six, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«React Router handles navigation in the browser without server round-trips, which is fine for SEO if configured correctly: » (Traduction) (Résumé en français de la section quarante-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
- Utiliser le History API, pas hash routing.
BrowserRouterutilisepushStateet produces clean, crawlable URLs (/products).HashRouterproduces/#/products, et Google ne peut pas reliably resolve hash-based URLs — le old AJAX-exploration scheme que fait les fonctionner est deprecated. Utiliser le History API. - Le serveur doit handle ceux URLs aussi. Avec History API routing, chaque “page” nécessite
a réel URL le serveur peut respond à — critical pour SSR, et necessary donc a direct hit
or refresh on
/productsne fait pas 404. <Link>renders a réel anchor. React Router’s<Link>component outputs an<a href>, qui est crawlable. Navigation construit ononClickhandlers sans an anchor est pas crawlable — Google seulement suit réel<a href>liens.
Managing metadata: react-helmet, react-helmet-async, et React 19’s native balises
Via React 18, React jamais mis à jour le document <head> on route changements natively —
chaque route’s <title>, meta description, canonical, et Ouvrir Graph / Twitter balises avait
à être définir par a library. React 19 modifié que: components peut rendre <title>,
<meta>, et <link> balises directement, et React hoists les à <head> on son propre —
fonctionnement avec client-seulement apps, streaming SSR, et Serveur Components alike. React 19,2 est
le actuel stable release as de mid-2026, donc ce maintenant s’applique à quelconque app on a actuel
React version.
Que signifie le correct réponse dépend on votre React version et ce que vous en réalité besoin:
«- React 19, standalone app, only basic tags. Render <title>/<meta>/<link> in
your components directly — no library needed.
» (Traduction) (Résumé en français de la section cinquante-deux, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- React 19, but you need htmlAttributes/bodyAttributes, SSR context
serialization, onChangeClientState, prioritizeSeoTags, or titleTemplate. Native
hoisting doesn’t cover these — use react-helmet-async. Its own docs call this out
directly: without those specific needs, you may not need the package at all on React 19.
» (Traduction) (Résumé en français de la section cinquante-deux, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«- React 18 or earlier, standalone app. Native hoisting doesn’t exist yet — use
react-helmet-async. It’s actively maintained (major version 3, and it detects your
React version at runtime) and supports SSR.
» (Traduction) (Résumé en français de la section cinquante-deux, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
«- The original react-helmet. Don’t use it, on any React version. It’s unmaintained
— no release since 2020 — and has known bugs under React 18’s concurrent rendering.
» (Traduction) (Résumé en français de la section cinquante-deux, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Next.js apps. Use Next’s own Metadata API (the metadata export /
generateMetadata in the App Router) regardless of React version — don’t bolt on
Helmet, and don’t rely on native React tag hoisting either. The framework owns the
document in a Next.js app.
» (Traduction) (Résumé en français de la section cinquante-deux, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.)
Un reliability règle carries over depuis JavaScript SEO généralement, et s’applique aucun matter qui de le ci-dessus vous utiliser: HTML-level metadata beats JS-injected metadata. A canonical balise injected par client-side JavaScript est far moins fiable que un présent dans le serveur-rendu HTML — qui est un autre argument pour SSR/SSG.
AI robots d’exploration faire ce urgent
Le 2026 wrinkle: rendu behavior pour GPTBot (OpenAI), ClaudeBot (Anthropic), PerplexityBot, et autre agents est provider- et version-spécifique. A CSR React app ships chaque robot d’exploration le même vide shell le premier Googlebot récupérer voit, et actuel provider documentation ne fait pas establish un shared rendre étape que va fill il dans. As generative moteurs become a bigger discovery surface, SSR/SSG arrête étant a Google-seulement concern: raw HTML maximizes coverage sans assuming a universal robot d’exploration limitation. (Le CMS headless topic covers ce AI-robot reality dans plus depth.)
Testing ce que Google en réalité sees
ne pas confiance votre navigateur — votre DevTools Inspector montre le rendu DOM (post-JavaScript), qui est exactly ce que a robot-sans-JS fait pas voir. Utiliser le correct outils:
- View Source vs. Inspect Element. View Source est le raw HTML (ce que robots d’exploration obtenir avant JS). Inspect Element est le rendu DOM. Si contenu est dans Inspect mais manquant depuis View Source, c’est JavaScript-dependent.
- Inspection d’URL Outil (Search Console) — le la plupart authoritative vérifier. Exécuter a actif tester et regarder à le rendu HTML, le screenshot, et le page resources / console messages à voir ce que Google en réalité rendu et ce que failed à charger.
- Résultats enrichis Tester — a rapide rendu-HTML vérifier sans verifying le site.
- Disable JavaScript dans DevTools et reload — a rapide simulation de a robot d’exploration que ne fait pas execute JS (et a decent proxy pour ce que AI robots d’exploration voir).
- Search Console Coverage rapport — “Discovered, currently not indexed” peut signal a rendre queue backlog; clusters de duplicate pages peut signal le rendre-timeout boilerplate trap.
- JS-rendu robots d’exploration — Ahrefs Site Audit et Screaming Frog (JS-rendu mode) rendre pages à scale donc vous pouvez diff raw vs. rendu à travers le entier site.
Suivant.js and Remix (the practical réponse)
«If SEO matters and you’re on raw CSR React, migrating to a framework that renders on the server is usually the right move. Next.js is purpose-built for this — SSR and SSG out of the box, ISR, the App Router, a built-in Metadata API, automatic code splitting, and image optimization. Remix is the web-standards alternative, built on fetch/Request/Response with SSR by default and a strong progressive-enhancement story. Next.js gets its own deep dive — I’m keeping it brief here on purpose. The point for React SEO is narrower: the framework exists to move your content out of the browser-only render step and into the initial HTML. » (Traduction) (Résumé en français de la section soixante, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
React est bon pour le SEO quand vous treat rendu as an architecture décision plutôt que an afterthought. Pick SSR or SSG pour n’importe quoi que nécessite à classer, garder votre liens et routing honest, manage metadata per route, et let Google’s propre outils — pas votre navigateur — tell vous ce que en réalité rendu.
AI summary
A condensed prendre on the Avancé version:
«- React isn’t bad for SEO — CSR by default is. React the library supports client,
server, static, and streaming rendering; it’s the default CRA/Vite toolchain (no
server) that ships an empty <div id="root"> shell and builds the DOM in the
browser, so the raw HTML a crawler fetches has no content.
» (Traduction) (Résumé en français de la section soixante-six, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Google can render React via the Web Rendering Service (evergreen Chromium), but
rendering is queued separately, can be delayed, and is stateless (no
cookies/localStorage/sessionStorage between loads).
» (Traduction) (Résumé en français de la section soixante-six, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«- The render-timeout trap: if main content loads slowly, rendering times out and
Google indexes a boilerplate-only page. Across many URLs those look identical and
get flagged as duplicates (Gary Illyes’s documented failure mode). Fix: load content
first — or better, don’t depend on the render step (SSR/SSG).
» (Traduction) (Résumé en français de la section soixante-six, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Rendering strategies, best→worst for SEO: SSG (lowest risk) ≈ SSR ≈ pre-render >
ISR/hybrid > CSR (highest risk). Dynamic rendering is deprecated — Google
recommends SSR, static rendering, or hydration.
» (Traduction) (Résumé en français de la section soixante-six, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
«- No ranking bonus for SSR — Mueller: “no SEO ranking bonuses for implementing it one
way or another.” It just makes content reliably indexable.
» (Traduction) (Résumé en français de la section soixante-six, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Hydration is a bug boundary, not a technique: SSR/SSG apps hydrate with
hydrateRoot (not createRoot), which expects the client’s first render to match the
server’s exactly. React warns on mismatches in dev but doesn’t guarantee patching them
— treat mismatches as bugs and verify server vs. post-hydration DOM directly.
» (Traduction) (Résumé en français de la section soixante-six, sous-partie six : le texte source est conservé pour vérification lors de la relecture francophone.)
«- React Router: use History API (BrowserRouter), not hash routing; the server must
handle those URLs; <Link> renders crawlable <a href> — onClick-only nav doesn’t.
» (Traduction) (Résumé en français de la section soixante-six, sous-partie sept : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Metadata: React 19 natively hoists <title>/<meta>/<link> to <head> for
standalone apps needing only the basics. On React 18, or for advanced needs (SSR
context, titleTemplate), use react-helmet-async — never the original
react-helmet, unmaintained since 2020. In Next.js, use the Metadata API
regardless of React version. HTML-level beats JS-injected.
» (Traduction) (Résumé en français de la section soixante-six, sous-partie huit : le texte source est conservé pour vérification lors de la relecture francophone.)
«- AI-crawler rendering is provider-specific — CSR React depends on client
execution that each crawler may or may not support. SSR/SSG puts content in the
initial HTML and maximizes coverage.
» (Traduction) (Résumé en français de la section soixante-six, sous-partie neuf : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Test with View Source vs. Inspect, URL Inspection (rendered HTML + screenshot + console),
Rich Results Test, JS-disabled reload, and a JS-rendering crawler.
» (Traduction) (Résumé en français de la section soixante-six, sous-partie dix : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Next.js / Remix are the practical fix — they move content into the initial HTML.
» (Traduction) (Résumé en français de la section soixante-six, sous-partie onze : le texte source est conservé pour vérification lors de la relecture francophone.)
Documentation officielle
Primary-source documentation from the moteur de recherches.
- Comprendre JavaScript SEO Basics — le explorer → rendre → indexer pipeline, SPAs, le History API, URL canoniques avec JS, et meaningful Code d’état HTTPs.
- Corriger Recherche-Related JavaScript Problèmes — soft-404 handling dans SPAs, le stateless renderer (aucun cookies/localStorage), et testing avec Inspection d’URL.
- Dynamic Rendu (deprecated workaround) — pourquoi Google deprecated il et ce que à utiliser à la place (SSR, static rendu, hydration).
- Introducing a nouveau JavaScript SEO video series — Martin Splitt’s series, covering React, Angular, et Vue précisément.
- Dans-Depth Guide à Comment Recherche Google Fonctionne — où rendu sits dans explorer → indexer → servir.
Bing / Microsoft
- Le nouveau evergreen Bingbot (Microsoft Edge) — Bingbot rendu JavaScript via le même Chromium plateforme as Googlebot.
- bingbot Series: JavaScript, Dynamic Rendu, et Cloaking — Bing’s older (2018) prendre; utile pour le historical dynamic-rendu recommendation.
Technique référence
- React v19 (release notes) — native prise en charge pour rendu
<title>,<meta>, et<link>balises dans components, hoisted automatiquement à<head>. - createRoot / hydrateRoot (React docs) — le client-rendre vs. hydration API split, et le caveat que mismatches ne sont pas guaranteed à être patched.
- react-helmet-async (npm) — le maintained fork pour managing
<head>dans standalone React apps, React 18 or avancé React 19 nécessite.
Quotes from the source
On-le-record statements depuis Google’s Recherche team. Chaque recherche-moteur deep lien jumps à le quoted passage on le page source; le staff citations ci-dessous sont lié à le coverage que reproduced les.
Google docs — SPAs et dynamic rendu
«- “Single-page applications (SPA) are websites that load an HTML document once and fetch any additional content using JavaScript APIs.” — Google Search Central docs. Jump to quote » (Traduction) (Résumé en français de la section soixante-dix-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- “Dynamic rendering was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines.” — Google Search Central docs. Jump to quote » (Traduction) (Résumé en français de la section soixante-dix-neuf, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
Martin Splitt, Google — comment JavaScript pages sont indexé
«- “What we do is we do an HTTP request, and we get something back, right — some HTML, maybe it’s a barebone HTML and all it does is load the JavaScript and run the JavaScript. Then, this HTML that we got from the original HTTP GET request from the crawl, goes into rendering. Rendering runs JavaScript — boom!, a lot of content happens that wasn’t there before.” Read the coverage (Search Engine Journal) » (Traduction) (Résumé en français de la section quatre-vingt-un, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- On the two-waves model being imprecise: “there’s no such thing as the second wave of crawling-ish. The wave is an oversimplification.” Read the coverage (Search Engine Roundtable) » (Traduction) (Résumé en français de la section quatre-vingt-un, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
Gary Illyes, Google — le rendre-timeout duplicate-contenu trap
«- “I have a bunch of emails in my inbox where the issue is that the centerpiece took forever to load, so rendering timed out (my most likely explanation) and we were left with a bunch of pages that only had the boilerplate. With only the boilerplate, those pages are dups.” » (Traduction) (Résumé en français de la section quatre-vingt-trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- “Do you have a JavaScript-heavy site and you see lots of dups reported in Search Console? Try to restructure the js calls such that the content (including marginal boilerplate) loads first and see if that helps.” Read the post (LinkedIn) » (Traduction) (Résumé en français de la section quatre-vingt-trois, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
John Mueller, Google — aucun ranking bonus pour rendering choice
- “Là sont aucun SEO classement bonuses pour implementing il un way or autre.” ils sont “just different ways of making the content indexable (as is client side rendering).” Lire le coverage (Moteur de recherche Roundtable)
React SEO checklist
A réussir to confirmer robots d’exploration peut voir and index votre React app:
- Important contenu apparaît dans View Source (raw HTML), pas seulement dans le rendu DOM — si c’est manquant, vous êtes selon CSR.
- Pages que besoin à classer utiliser SSR or SSG (Suivant.js, Remix, or a pre-rendre étape), pas raw rendu côté client.
- Principal contenu charge rapide et premier — aucun lent API waterfalls que pourrait trip le rendre timeout dans a boilerplate-seulement page.
- Routing utilise le History API (
BrowserRouter), pasHashRouter/#/URLs. - Le serveur peut respond à chaque client-side route (aucun 404 on direct hit or refresh).
- Navigation utilise réel
<a href>liens (React Router<Link>), pasonClick-seulement handlers on<div>/<button>. - Chaque route sets a unique
<title>, meta description, canonical, et OG balises que mettre à jour on navigation. - Metadata matches votre version: React 19 native
<title>/<meta>/<link>balises pour le basics, react-helmet-async pour React 18 or avancé nécessite (jamais le deprecatedreact-helmet), or le Suivant.js Metadata API si on Suivant.js. - Si serveur-rendu, vous êtes hydrating avec
hydrateRoot(pascreateRoot), et quelconque dev-mode hydration mismatch warning est treated as a bug à corriger. - Client-side “pas trouvé” routes retourner a réel 404 (or a
noindex), pas a soft-404 avec a200status. - JavaScript et CSS ne sont pas bloqué dans
robots.txt(Google ne va pas rendre depuis bloqué fichiers). - Aucun critical contenu dépend on cookies / localStorage / sessionStorage (le renderer est stateless).
- Verified dans Inspection d’URL: le rendu HTML et screenshot montrer votre contenu réel.
- Coverage rapport vérifié pour “Discovered, currently pas indexé” (rendre backlog) et duplicate clusters (rendre-timeout trap).
The mental models
1. Le seulement question que matters: qu’est-ce que dans le raw HTML? View Source avant quelconque JavaScript exécute est ce que a premier-récupérer robot d’exploration — et la plupart AI robots d’exploration, forever — voir. Si votre contenu n’est pas là, vous ont a React SEO problème regardless de comment bon lune page semble dans votre navigateur.
2. Rendu est a séparé, fallible étape. Explorer → rendre → indexer. CSR puts 100% de votre contenu on le far side de le rendre étape, qui est queued, delayed, stateless, et peut temps out. SSR/SSG déplacer votre contenu avant que étape. ne pas over-confiance le “deux waves” model — Splitt himself appelé il an oversimplification.
3. Le boilerplate-duplicate échec mode. Lent contenu + rendre timeout = chaque URL renders as header/nav/footer seulement = Google voit duplicates. Le corriger est structural: charger contenu premier, or arrêter selon le rendre étape.
4. Le rendu arbre de décision.
- Public contenu que doit classer or être cited par AI → SSG (static) or SSR (fresh).
- Mostly static (blog, docs, marketing) → SSG, or ISR on a timer.
- Frequently modification, doit être fresh → SSR.
- Logged-dans dashboard, pas meant à être indexé → CSR est fine.
- Nouveau construire que nécessite SEO → reach pour Suivant.js / Remix, pas dynamic rendu.
5. HTML-premier, JS-deuxième pour chaque SEO signal. Contenu, liens, canonicals, titles, données structurées — obtenir les dans le serveur-rendu HTML. Treat JS-injected SEO signaux (notamment JS balise canonicals et react-helmet on CSR) as a fallback, pas le plan: Google voit les late, et AI robots d’exploration pas à tout.
React SEO — cheat sheet
Rendering modes En un coup d’œil
| Mode | Contenu dans initial HTML? | SEO risque | Utiliser pour |
|---|---|---|---|
| CSR (raw React) | Aucun | Highest | Logged-dans dashboards, pas-indexé apps |
| Pre-rendu (react-snap) | Oui (construire temps) | Faible | Petit, mostly-static sites |
| SSG | Oui (construire temps) | Lowest | Blogs, docs, marketing |
| SSR | Oui (per requête) | Faible | Fresh, dynamic contenu |
| ISR / hybrid (Suivant.js) | Oui | Faible | Hourly/daily contenu |
| Dynamic rendu | Bot-seulement | Deprecated | ne pas — utiliser SSR/SSG/hydration |
Courant React SEO mistakes → fixes
| Mistake | Corriger |
|---|---|
| Contenu seulement dans rendu DOM (CSR) | SSR / SSG / pre-rendre |
Hash URLs (/#/path) | History API (BrowserRouter) |
onClick navigation, aucun anchor | Réel <a href> / React Router <Link> |
| Meta balises ne pas mettre à jour on route | React 19: native <title>/<meta>/<link>. Older/avancé: react-helmet-async. Suivant.js: Metadata API |
react-helmet (original, quelconque React version) | Switch à react-helmet-async or React 19 native balises |
createRoot utilisé on serveur-rendu HTML | Utiliser hydrateRoot à la place — createRoot discards le serveur markup |
| Hydration mismatch warning suppressed | Treat il as a bug et corriger le serveur/client difference |
| Lent contenu → rendre timeout → dups | Charger principal contenu premier; déplacer à SSR/SSG |
Client-side 404 renvoie 200 | Réel 404 status or noindex |
Bloqué .js / .css dans robots.txt | Autoriser les — Google ne va pas rendre bloqué fichiers |
| Contenu gated on cookies/localStorage | ne pas — le renderer est stateless |
Rapide règles
- Le renderer est evergreen Chromium, queued, stateless, et times out.
- Aucun classement bonus pour SSR — c’est à propos de fiable indexability (Mueller).
- AI-robot rendu varies par provider → raw HTML est le safest coverage baseline.
- Dans Suivant.js, utiliser le Metadata API — pas React Helmet.
- Bing renders JS (via Edge) mais moins reliably; SSR/SSG est le sûr appel là aussi.
Vérifier ce que le serveur sends avant React runs
Put representative indexable routes in urls.txt. Ce trouve CSR shells and manquant
server-rendered head markup in the raw réponse:
while IFS= read -r url; do
html=$(mktemp)
status=$(curl -sS -o "$html" -w '%{http_code}' "$url")
bytes=$(wc -c < "$html" | tr -d ' ')
title_count=$(grep -Eio '<title>[^<]*</title>' "$html" | wc -l | tr -d ' ')
canonical_count=$(grep -Eio '<link[^>]+rel=["'"']canonical["'"'][^>]*>' "$html" | wc -l | tr -d ' ')
printf '%s\t%s\tbytes=%s\ttitles=%s\tcanonicals=%s\n' "$status" "$url" "$bytes" "$title_count" "$canonical_count"
rm -f "$html"
done < urls.txtPetit byte size est seulement a examiner signal, pas an erreur par itself. Comparer flagged raw réponses avec rendu HTML et confirmer que principal texte et crawlable liens sont présent.
Outils pour auditing React SEO
«- View Source vs. Inspect Element — the fastest first check. View Source is the raw HTML (what a crawler gets before JS); Inspect Element is the rendered DOM. Content in Inspect but not View Source is JavaScript-dependent. » (Traduction) (Résumé en français de la section cent dix-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- URL Inspection (Google Search Console) — the source of truth. Run a live test, then view the rendered HTML, the screenshot, the page resources (what loaded vs. was blocked), and console messages to see exactly what Google rendered. » (Traduction) (Résumé en français de la section cent dix-sept, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- Rich Results Test — a quick rendered-HTML and structured-data check for a single URL without verifying the site. » (Traduction) (Résumé en français de la section cent dix-sept, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.) «- Chrome DevTools — disable JavaScript (Command Menu → “Disable JavaScript”) and reload to inspect what an HTML-only fetcher receives. This is a coverage check, not proof of any named AI crawler’s current rendering behavior. » (Traduction) (Résumé en français de la section cent dix-sept, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.) «- Search Console Coverage report — watch “Discovered, currently not indexed” (render backlog) and duplicate clusters (the render-timeout boilerplate trap). » (Traduction) (Résumé en français de la section cent dix-sept, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.) «- JS-rendering crawlers — Ahrefs Site Audit and Screaming Frog SEO Spider (JS-rendering mode) execute JavaScript so you can diff raw vs. rendered HTML across the site. » (Traduction) (Résumé en français de la section cent dix-sept, sous-partie six : le texte source est conservé pour vérification lors de la relecture francophone.)
Mistakes React teams en réalité faire
Concrete patterns I garder seeing in CSR React apps que obtenir shipped, pas hypothetical ones. Chaque is a prevention déplacer — catch it avant it costs vous indexation.
Shipping raw CRA/Vite CSR pour pages que besoin to rank
Teams ship Créer React App or Vite + React straight à production pour marketing pages,
blog posts, or produit pages — le exact contenu que nécessite à montrer up dans recherche.
Pourquoi c’est incorrect: le serveur sends an presque-empty <div id="root"> shell; votre réel
contenu seulement exists après JavaScript exécute, donc c’est delayed par Google’s rendre queue et
peut être invisible à quelconque AI robot d’exploration que récupère initial HTML sans client execution.
Que faire à la place: déplacer
n’importe quoi que nécessite à classer or être cited à SSR or SSG — Suivant.js or Remix sont le easiest
paths — et reserve raw CSR pour logged-dans, non-indexé surfaces comme dashboards.
Routing on hash URLs (HashRouter)
Reaching pour React Router’s HashRouter parce que c’est le chemin de le moins resistance —
aucun serveur config nécessaire, fonctionne on quelconque static host. Pourquoi c’est incorrect: Google ne peut pas
reliably resolve /#/products-style URLs; le old AJAX-exploration scheme que fait hash
fragments crawlable est deprecated. Que faire à la place: utiliser BrowserRouter (le
History API) et assurez-vous le serveur responds à chaque route il produces, notamment a
direct hit or refresh on a deep lien.
Building navigation on onClick au lieu de réel anchors
Wiring up navigation avec onClick handlers on a <div> or <button>, souvent parce que il
était easier à style or éviter par défaut lien behavior. Pourquoi c’est incorrect: Google seulement
suit réel <a href> liens — a <div> avec a click handler est invisible à exploration,
aucun matter comment il behaves pour a mouse. Que faire à la place: utiliser React Router’s
<Link> component, qui renders an réel <a href> sous le hood, or a plain anchor
balise pour external navigation.
Chargement principal content behind a slow API waterfall
Fetching le header et nav rapide, alors chaining plusieurs API calls avant le réel page contenu — le partie que rend chaque URL unique — apparaît. Pourquoi c’est incorrect: Google’s Web Rendu Service enforces a timeout; si votre centerpiece contenu charge slowly, rendu finishes avant il arrives, et Google est left indexation boilerplate-seulement pages que alors obtenir flagged as duplicates de chaque autre — le exact échec mode Gary Illyes décrit. Que faire à la place: restructure requêtes donc principal contenu charge premier, or supprimer le dependency on rendu côté client entirely avec SSR/SSG.
Encore en utilisant the original react-helmet
Reaching pour react-helmet pour per-route <title> et meta balises parce que c’est le
library chaque older tutorial recommends. Pourquoi c’est incorrect: le original package est
unmaintained — aucun release since 2020 — et a connu problèmes sous React 18’s concurrent
rendu et SSR. Que faire à la place: on React 19, rendre <title>/<meta>/<link>
directement dans votre components et let React hoist les (aucun library nécessaire pour le basics).
On React 18, or pour avancé nécessite comme SSR context serialization or titleTemplate, utiliser
react-helmet-async, le maintained fork. On Suivant.js, utiliser son built-dans Metadata API et
ne pas bolt Helmet on top de il.
Blocking JavaScript or CSS dans robots.txt
Blocking /static/js/ or a bundler’s asset folder dans robots.txt, parfois left over
depuis an old explorer-budget concern or copied depuis un autre site’s config. Pourquoi c’est
incorrect: Google ne peut pas rendre Ce que c’estn’t allowed à récupérer — a bloqué bundle signifie le
Web Rendu Service construit an incomplete (or vide) DOM, même though votre code source
est fine. Que faire à la place: autoriser robots d’exploration à récupérer votre JS et CSS, et confirmer il
avec le Inspection d’URL outil’s page-resources vérifier à voir rien critical est bloqué.
Testez vos connaissances: React SEO
Five rapide questions on making React apps crawlable et indexable. Pick an réponse pour chaque, alors vérifier.
Ressources utiles
Mon connexe writing
- React SEO: Meilleur Practices à Faire Il SEO-Friendly (Ahrefs) — le React SEO guide on Ahrefs, qui Je reviewed; ce article est le deeper, source-linked treatment.
- JavaScript SEO: A Definitive Guide (Ahrefs) — mon complet guide à le underlying rendu mechanics: DOM parity, le la plupart-restrictive-directive règle, canonical et meta-balise handling, et rendu choices. Lire ce pour le general cas behind React-spécifique corrections.
- Le Beginner’s Guide à SEO technique (Ahrefs) — où React/JavaScript SEO fits dans le bigger picture.
Mon speaking
- Comment Recherche Fonctionne (SlideShare) — mon walkthrough de exploration, rendu, indexation, et classement. (Mon standing disclaimer s’applique: “This is my understanding of systems… not going to be 100% complete or accurate.”)
«From around the industry » (Traduction) (Résumé en français de la section cent quarante-quatre, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- Understand JavaScript SEO Basics (Google) — primary-source docs on SPAs, the History API, and canonical/status-code handling. » (Traduction) (Résumé en français de la section cent quarante-quatre, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- Dynamic Rendering (deprecated) (Google) — why dynamic rendering is a workaround, not a long-term solution. » (Traduction) (Résumé en français de la section cent quarante-quatre, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.) «- Martin Splitt Explains How JavaScript Sites Are Indexed (Search Engine Journal) — the “barebone HTML … boom” explanation of the crawl → render → index flow. » (Traduction) (Résumé en français de la section cent quarante-quatre, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.) «- Gary Illyes on JS-heavy sites and duplicate content (LinkedIn) — the render-timeout-to-duplicates failure mode, in his own words. » (Traduction) (Résumé en français de la section cent quarante-quatre, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.) «- How to fix technical SEO issues on client-side React apps (Search Engine Land) — a real-world case study on auditing and fixing a CSR React app. » (Traduction) (Résumé en français de la section cent quarante-quatre, sous-partie six : le texte source est conservé pour vérification lors de la relecture francophone.) «- SSR vs. dynamic rendering — no ranking difference (Search Engine Roundtable) — Mueller’s “no SEO ranking bonuses” statement. » (Traduction) (Résumé en français de la section cent quarante-quatre, sous-partie sept : le texte source est conservé pour vérification lors de la relecture francophone.) «- react-helmet-async (npm) — the maintained head-management library for standalone React. » (Traduction) (Résumé en français de la section cent quarante-quatre, sous-partie huit : le texte source est conservé pour vérification lors de la relecture francophone.) «- The new evergreen Bingbot (Microsoft Edge) (Bing) — Bingbot rendering JS via Chromium, like Googlebot. » (Traduction) (Résumé en français de la section cent quarante-quatre, sous-partie neuf : le texte source est conservé pour vérification lors de la relecture francophone.)
Videos
- Recherche Google Central — JavaScript SEO series (YouTube) — Martin Splitt’s official video series covers SEO pour React, Angular, et Vue précisément, walking via le explorer → rendre → indexer traiter et le courant corrections. Series announcement · Channel
Journal des modifications
Mis à jour le 18 juil. 2026.
Résumé éditorial et détails enregistrés des changements.Détails des changements
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
Comparaison complète indisponible — aucun instantané antérieur n’a été archivé pour cette révision.