Guide Vue SEO
Vue 3 defaults à rendu côté client, donc le contenu n’est pas dans le raw HTML. Ce est comment faire Vue apps crawlable et indexable — router mode, @unhead/vue, prerendering avec vite-ssg, SSR/SSG avec Nuxt, hydration, et Core Web Vitals.
Vue 3 defaults à rendu côté client, donc a plain Vite + Vue app ships an vide HTML shell et construit lune page dans le navigateur. Google peut rendre il — mais rendu est delayed et async données peut être missed, et Bing et social scrapers souvent ne peut pas exécuter le JS à tout. Le corrections: utiliser Vue Router history mode (pas hash mode), manage <head> avec @unhead/vue, et put contenu dans le HTML avec prerendering (vite-ssg), SSR, or SSG via Nuxt. Dynamic rendu est deprecated — ne pas construire on il.
«> TL;DR — Vue builds your page in the browser by default. That means the raw
HTML a search engine first downloads is nearly empty — the real content only shows up after JavaScript runs. Google can usually handle this, but Bing and the bots that make social-share previews often can’t. The fixes: use Vue Router’s “history” mode for clean URLs, add a small library called
@unhead/vuefor your titles and descriptions, and for pages that need to rank, build the HTML ahead of time (prerendering or Nuxt) instead of only in the browser. » (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 Vue nécessite special SEO attention
Quand vous construire a site avec Vue 3 le normal façon (Vite + Vue), le serveur sends a tiny HTML fichier — basically an vide container — et a big JavaScript bundle. Le navigateur exécute que JavaScript à draw le réel page. Ce est appelé client-side rendu (CSR). Preuve à l’appui de cette affirmation A Vue application can render its interface in the browser with client-side JavaScript. Portée : Vue client-side rendering architecture. Niveau de confiance : élevé · Vérifié : Vue: SSR guide
A human jamais notices. A moteur de recherche pourrait. Le premier chose a robot d’exploration downloads est que nearly-empty container. Il a à exécuter votre JavaScript à voir n’importe quoi — et pas chaque robot d’exploration fait que bien.
- Google exécute an up-à-date version de Chrome et peut rendre votre Vue app. Mais il fait le rendu plus tard, dans a queue, et si votre contenu waits on a lent datune requête, Google peut déplacer on avant il charge.
- Bing, DuckDuckGo, et social-preview bots (le ones que faire le little card quand vous paste a lien dans X, Slack, or iMessage) sont beaucoup moins fiable à running JavaScript. On a plain Vue app, votre social previews peut come up blank.
The three choses to obtenir correct
-
Utiliser “history” mode in Vue Router, pas “hash” mode. Hash-mode URLs regarder comme
example.com/#/about. Vue Router’s propre docs dire hash mode “has a bad impact in SEO.” UtilisercreateWebHistory()so votre URLs regarder commeexample.com/about. Preuve à l’appui de cette affirmation Vue Router recommends HTML5 history mode for normal-looking URLs and warns that hash mode has a negative SEO effect. Portée : Vue Router history modes. Niveau de confiance : élevé · Vérifié : Vue Router: History modes -
Manage votre titles et meta balises avec
@unhead/vue. Out de le box, chaque Vue page shares le même titre et description.@unhead/vuelets chaque page définir son propre — notamment le Ouvrir Graph et Twitter balises que drive social previews. -
Put votre contenu dans le HTML pour pages que besoin à classer. Au lieu de building tout dans le navigateur, construire il ahead de temps donc le contenu est déjà là quand a robot d’exploration arrives. Le facile on-ramp est prerendering avec a outil appelé
vite-ssg. Pour bigger or plus dynamic sites, Nuxt (le official Vue framework pour ce) fait il pour vous.
Devrait vous simplement utiliser Nuxt?
Pour la plupart sites où SEO en réalité matters, oui — et Vue’s propre documentation points
vous là. Nuxt handles le rendu, le meta balises, sitemaps, et robots.txt pour
vous. Si votre site est fairly static (a marketing site, docs, a blog), vite-ssg est
a lighter option que ne fait pas exiger switching frameworks.
Vouloir le deeper version — comment Google’s rendre queue fonctionne, le @unhead/vue code,
prerendering vs. SSR, hydration mismatches, et Core Web Vitals? Switch à le
Avancé tab.
«> TL;DR — Vue 3 is CSR by default, so the content isn’t in the raw HTML —
Google renders it later via its evergreen Chromium WRS, but the render is queued and async data fetched in
onMountedcan be missed, and Bing/social scrapers often don’t run the JS at all. Non-negotiables: Vue RoutercreateWebHistory()(hash mode has “a bad impact in SEO”),<head>via@unhead/vue/useSeoMeta(), and a rendering strategy that gets content into HTML —vite-ssgprerendering for content-stable sites, Nuxt for full SSR/SSG. Dynamic rendering is deprecated;prerender-spa-pluginis legacy. Watch hydration mismatches (a server/client content delta is an SEO problem, not just a perf one) and the CSR bundle’s hit on LCP. For the framework-agnostic version of all of this, see JavaScript SEO. » (Traduction) (Résumé en français de la section dix-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
The par défaut Vite + Vue scaffold is client-side rendered
A plain npm create vue@latest app (Vite + Vue) ships a near-empty HTML shell et
a JavaScript bundle. Le navigateur executes que bundle à construire le DOM. Ce est
fine pour utilisateurs et a problème pour robots d’exploration: le raw HTML contient presque aucun
contenu, et tout dépend on rendu.
c’est a property de le par défaut scaffold, pas a ceiling on Vue itself — Vue core
aussi prend en charge serveur rendu (createSSRApp) et static generation as
premier-class paths, et Vue’s propre SSR guide steers la plupart production SSR/SSG fonctionner
toward Nuxt plutôt que a hand-rolled setup. Donc avant reaching pour a corriger, vérifier
ce que votre app est en réalité shipping: a bare Vite SPA avec aucun rendu config est
CSR; le même app behind Nuxt or vite-ssg n’est pas.
«Vue’s own SSR guide is direct about the upside of not doing this: with server-side rendering, “the search engine crawlers will directly see the fully rendered page.” The flip side is what you ship by default — content that only exists after JavaScript runs. Preuve à l’appui de cette affirmation Vue server-side rendering sends rendered HTML so crawlers can directly see page content. Portée : Vue SSR benefits; does not guarantee indexing. Niveau de confiance : élevé · Vérifié : Vue: SSR guide » (Traduction) (Résumé en français de la section vingt et un, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
(Vue 2 reached fin of life in December 2023; everything ici is Vue 3.)
Comment Googlebot handles a Vue app
Google processes JavaScript dans phases — explorer le raw HTML, alors rendre il dans an evergreen, headless Chromium instance (le Web Rendu Service), alors indexer le rendu résultat. Deux choses suivre depuis que:
- Rendu est queued et delayed. Une page sits dans le rendre queue — généralement seconds à minutes, mais il peut spike. Contenu que exists seulement après JS exécute est pas immédiatement indexable; contenu dans le raw HTML est.
- Async données est le réel risque. Synchronous JavaScript renders reliably. Données
récupéré depuis an API après mount n’est pas guaranteed à être caught. Vue’s SSR guide
dit il plainly: “Si votre app commence avec a chargement spinner, alors récupère contenu
via Ajax, le robot d’exploration ne va pas wait pour vous à finish. Ce signifie si vous ont
contenu récupéré asynchronously on pages où SEO est important, SSR pourrait être
necessary.” Practically: données récupéré dans
onMountedest client-seulement et invisible à robots d’exploration que ne pas rendre — et à risque même avec le ones que faire.
John Mueller a décrit le échec mode pour SPA-style setups où le static HTML est mostly identical et tout le unique contenu dépend on JavaScript: si que JS ne peut pas être executed correctement, lune pages fin up looking le même à Google, et le focus stays on le boilerplate HTML plutôt que le JS-chargé contenu. Le lesson est le même as le broader JavaScript SEO page: obtenir le contenu dans le DOM, rapide et reliably.
Bing et social bots sont pire à ce que Google. Bing a aucun rendu pipeline comparable à Google’s, et social preview scrapers (X, Slack, iMessage) généralement ne pas exécuter JavaScript à tout — donc a bare CSR Vue app produces vide share previews. Si Bing trafic or social sharing matters, prerendering or SSR n’est pas optional.
Vue Router: utiliser createWebHistory(), pas hash mode
«Vue Router has two history modes. Hash mode (createWebHashHistory()) produces
URLs like example.com/#/about; Vue Router’s docs say it “does however have a bad
impact in SEO” because everything after the # is a fragment the server ignores. Preuve à l’appui de cette affirmation Vue Router hash history uses a URL fragment that is not sent to the server and is discouraged for SEO. Portée : Vue Router hash history. Niveau de confiance : élevé · Vérifié : Vue Router: History modes
Use HTML5 history mode:
» (Traduction) (Résumé en français de la section vingt-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [/* ... */],
})History mode donne clean URLs (example.com/about) but exige a server
fallback — quelconque direct requête to a route has to serve index.html so Vue peut
prendre over, sinon direct hits 404. Configurer que catch-all on votre host (Nginx
try_files, an SPA rewrite on Netlify/Vercel/Cloudflare, etc.).
«Scope that rewrite carefully — a catch-all that’s too broad also serves
index.html for missing static assets, real API routes, or pages you actually
want to 404. That silently undoes the soft-404 guidance below and can hide a
broken link behind a page that looks like it “worked.”
» (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.)
«For genuine not-found states, avoid soft-404s — a client-side “not found” view that
still returns 200 can get indexed as an empty shell. Google’s guidance is to
either redirect to a URL that returns a real 404 status or add a
<meta name="robots" content="noindex"> to error pages, and to use the History API
for routing between views.
» (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.)
«## Head and meta management: @unhead/vue
» (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.)
«By default every Vue route shares one <title> and one meta description. The tag
history here matters because the old answers are dead ends:
» (Traduction) (Résumé en français de la section trente-cinq, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
vue-meta— le Nuxt 2-era library. Legacy.@vueuse/head— son successor, maintenant sunset.@unhead/vue— le actuel community standard, et ce que vous devez utiliser pour a non-Nuxt Vue 3 app.
Le ergonomic entry point est le useSeoMeta() composable — type-sûr, XSS-sûr,
et aware de 100+ meta balises notamment Ouvrir Graph et Twitter Card:
import { useSeoMeta } from '@unhead/vue'
useSeoMeta({
title: 'Vue SEO Guide',
description: 'How to make a Vue 3 app crawlable and indexable.',
ogTitle: 'Vue SEO Guide',
ogDescription: 'How to make a Vue 3 app crawlable and indexable.',
twitterCard: 'summary_large_image',
})«Meta can be reactive — pass a getter or computed value and the tags update when your data does. For canonical tags, the safest pattern is still HTML, not JS: Google’s guidance is that “the best way to set the canonical URL is to use HTML,” and if you must inject it with JavaScript, always set it to the same value the HTML would. (I tested JS canonicals at Ahrefs and found Google does respect them — it even led Google to add an exception to its docs — but HTML is still the lower-risk path.) » (Traduction) (Résumé en français de la section trente-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Pick a rendering strategy
Ce est le décision que en réalité moves le needle. Même menu as le framework- agnostic JavaScript SEO page, applied à Vue.
Rendu côté client (CSR) — le par défaut, et le risky un. Acceptable pour app-like pages behind a login, dashboards, et n’importe quoi vous ne pas besoin indexé. Pas acceptable pour contenu que doit classer or être shared.
Prerendering avec vite-ssg. Pour contenu-stable Vue 3 SPAs, vite-ssg
generates static HTML à construire temps — swap votre construire script depuis vite build à
vite-ssg build. Il ships @unhead/vue construit dans. Great pour marketing sites, docs,
et blogs; pas a substitute pour SSR on highly dynamic, per-requête pages. Remarque que
le old webpack-era prerender-spa-plugin est legacy et effectively
unmaintained — vite-ssg (or Nuxt) est le modern replacement.
«Server-side rendering. Vue’s official guide covers a manual SSR setup with
@vue/server-renderer, but it explicitly steers most projects to a meta-framework
rather than rolling your own — and for simple cases it even says “if you’re only
investigating SSR to improve the SEO of a handful of marketing pages … then you
probably want SSG instead of SSR.” If you do roll manual SSR, create the app,
router, and store fresh per request: on a long-running Node server, module-level
singletons get reused across requests, and mutating shared state with one user’s
data can leak it into another user’s response. That’s one more reason Vue’s docs
point most projects at Nuxt, which handles per-request isolation for you.
» (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.)
Nuxt — le recommended complet solution. Nuxt donne vous SSR et SSG out de le
box, built-dans useSeoMeta() et head management, et le @nuxtjs/seo module pour
sitemaps, robots.txt, et données structurées. Pour la plupart Vue projects où SEO matters,
ce est le chemin Vue’s propre docs point à. (Nuxt a son propre depth — covered
séparément; treat ce as le cross-lien, pas le deep dive.)
Dynamic rendu — ne pas. Diffusion prerendered HTML à bots et le SPA à utilisateurs était toujours a workaround, et Google deprecated il dans 2024, removing le implementation docs. Construire on SSR or SSG à la place.
Pour documentation précisément, VitePress est le Vue-native static site
generator. Chaque page ships as plain HTML — aucun JS rendu barrier — et SEO est
configuré via frontmatter (title, description, head) or le transformHead
construire hook pour canonical/dynamic balises.
Hydration mismatches are an SEO problem, pas simplement a perf un
Quand vous faire SSR/SSG, le client mounts avec createSSRApp() — pas le plain
createApp() — et hydrates le serveur-rendu HTML au lieu de rebuilding il
depuis scratch. Si le serveur HTML et le client rendre diverge, Vue discards et
re-renders le mismatched nodes. Dans SEO terms, que signifie le contenu Google indexé
depuis le serveur rendre peut differ depuis ce que le utilisateur voit après hydration — a
qualité-signal inconsistency, pas simplement a flicker. Courant causes: invalide HTML
nesting, random valeurs dans templates, et date/temps discrepancies entre serveur et
client. Vue 3,5+ ajoute data-allow-mismatch à suppress le mismatch warning
selectively où a difference est intentional — il quiets le console, il ne fait pas
faire le serveur et client sortie equivalent, donc ne pas reach pour il simplement à silence
a mismatch vous haven’t en réalité diagnosed.
Core Web Vitals sont a Vue-spécifique concern
Par défaut CSR Vue ships a grand JS bundle que a à download, parse, et execute avant le largest contenu paints — donc LCP suffers si vous ne faites pashing. Levers:
- Code splitting (Vite’s par défaut) et lazy-chargé routes donc vous ne pas ship le entier app up front.
fetchpriority="high"on le LCP hero image.- Vapor Mode — an opt-dans compiler mode que bypasses le virtual DOM pour eligible components, qui peut cut hydration coût on SSR pages. c’est Vue 3,6, pas 3,5 — encore experimental (beta/release-candidate as de mid-2026, pas yet dans le stable 3,5.x line) — worth watching, pas quelque chose à depend on dans production aujourd’hui.
Données structurées in Vue
Google executes JavaScript avant reading données structurées, donc injecting JSON-LD
fonctionne — @unhead/vue’s useHead() avec a script de type
application/ld+json est le fiable modèle. Parce que il dépend on rendu,
confirmer il avec Inspection d’URL plutôt que assuming Google saw il.
Où ce fits
Vue SEO est un instance de le general JavaScript SEO problème — parity, interaction, state, timing — et il shares presque tout avec le CMS headless situation, où le rendu mode de le frontend decides le résultat.
Un caveat que s’applique à chaque option ci-dessus: SSR et SSG obtenir votre contenu dans le HTML, mais aucun guarantees indexation, rankings, Core Web Vitals, or que hydration va match le serveur sortie exactly. Ils supprimer le JavaScript-rendu barrier — le rest de SEO (et correctness) est encore on vous.
Si vous remember un chose: obtenir votre contenu dans le HTML. Tout sinon est detail.
AI summary
A condensed prendre on the Avancé version:
«- The default Vite + Vue scaffold is CSR — a plain npm create vue@latest app
ships a near-empty HTML shell and builds the DOM in the browser. That’s a property
of the bare scaffold, not a ceiling on Vue itself — Vue core also supports SSR
(createSSRApp) and SSG as first-class paths.
» (Traduction) (Résumé en français de la section soixante-trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Google renders Vue, but with caveats — its evergreen Chromium WRS runs the JS,
but rendering is queued/delayed and async data (e.g. fetched in onMounted) can
be missed. Vue’s SSR docs: a crawler “will not wait for you to finish” an Ajax
fetch behind a spinner.
» (Traduction) (Résumé en français de la section soixante-trois, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Bing and social scrapers are worse — they often don’t run JS at all, so a bare
CSR Vue app produces empty share previews.
» (Traduction) (Résumé en français de la section soixante-trois, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Router: use createWebHistory(), not hash mode (hash has “a bad impact in
SEO”). History mode needs a server index.html fallback — scoped so it doesn’t
also swallow real static assets, API routes, or intended 404s. Avoid soft-404s.
» (Traduction) (Résumé en français de la section soixante-trois, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Head/meta: @unhead/vue with useSeoMeta() is the current standard;
vue-meta is legacy, @vueuse/head is sunset. Prefer HTML canonicals.
» (Traduction) (Résumé en français de la section soixante-trois, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Rendering strategy decides it: CSR (risky, OK for app pages) → vite-ssg
prerendering (content-stable sites) → SSR / SSG via Nuxt (the recommended full
solution). prerender-spa-plugin is legacy; dynamic rendering is deprecated. If
you roll manual SSR, build the app/router/store fresh per request to avoid
cross-request state leaks.
» (Traduction) (Résumé en français de la section soixante-trois, sous-partie six : le texte source est conservé pour vérification lors de la relecture francophone.)
«- VitePress for docs sites (plain static HTML).
» (Traduction) (Résumé en français de la section soixante-trois, sous-partie sept : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Hydration uses createSSRApp(); mismatches create a server/client content
delta — an SEO quality issue, not just a flicker. Vue 3.5+‘s data-allow-mismatch
suppresses the warning for intentional cases — it doesn’t make the two renders
equivalent.
» (Traduction) (Résumé en français de la section soixante-trois, sous-partie huit : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Core Web Vitals: big CSR bundle hurts LCP — code-split, lazy routes,
fetchpriority="high", and (experimental, Vue 3.6 beta/RC — not stable yet)
Vapor Mode.
» (Traduction) (Résumé en français de la section soixante-trois, sous-partie neuf : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Structured data via @unhead/vue useHead() JSON-LD; verify with URL
Inspection.
» (Traduction) (Résumé en français de la section soixante-trois, sous-partie dix : le texte source est conservé pour vérification lors de la relecture francophone.)
«- No option here guarantees indexing, rankings, CWV, or hydration parity — SSR/SSG
remove the JS-rendering barrier; the rest of SEO is still on you.
» (Traduction) (Résumé en français de la section soixante-trois, sous-partie onze : le texte source est conservé pour vérification lors de la relecture francophone.)
«## Official documentation » (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.)
«Primary-source documentation from Vue and the search engines. » (Traduction) (Résumé en français de la section soixante-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«Vue
» (Traduction) (Résumé en français de la section soixante-huit, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Server-Side Rendering (SSR) | Vue.js — the SEO benefit of SSR, the async/spinner caveat, and the SSG-for-marketing-pages recommendation.
» (Traduction) (Résumé en français de la section soixante-huit, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Different History modes | Vue Router — createWebHistory() vs. hash mode, the SEO note, and the server fallback requirement.
» (Traduction) (Résumé en français de la section soixante-huit, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
«- useSeoMeta() · Unhead — the current @unhead/vue composable for type-safe meta management.
» (Traduction) (Résumé en français de la section soixante-huit, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Site Config | VitePress and Frontmatter Config | VitePress — SEO configuration for Vue-powered docs sites.
» (Traduction) (Résumé en français de la section soixante-huit, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.)
«- antfu-collective/vite-ssg | GitHub — build-time prerendering for Vue 3 SPAs.
» (Traduction) (Résumé en français de la section soixante-huit, sous-partie six : le texte source est conservé pour vérification lors de la relecture francophone.)
«Google » (Traduction) (Résumé en français de la section soixante-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- Understand the JavaScript SEO basics — two-phase processing, the History API recommendation, soft-404 handling, and HTML canonicals. » (Traduction) (Résumé en français de la section soixante-neuf, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- Dynamic Rendering as a workaround — now flagged as deprecated; SSR/static rendering/hydration recommended instead. » (Traduction) (Résumé en français de la section soixante-neuf, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.) «- Introducing a new JavaScript SEO video series — Google’s official JS SEO series (includes the Vue.js episode). » (Traduction) (Résumé en français de la section soixante-neuf, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
«## Quotes from the source » (Traduction) (Résumé en français de la section soixante-douze, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
On-le-record statements depuis Vue et Google. Chaque lien est a deep lien que jumps à le quoted passage on le page source.
Vue — SSR & SEO
«- “Better SEO: the search engine crawlers will directly see the fully rendered page.” — Vue.js SSR guide. Jump to quote » (Traduction) (Résumé en français de la section soixante-quinze, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- “As of now, Google and Bing can index synchronous JavaScript applications just fine. Synchronous being the key word there. If your app starts with a loading spinner, then fetches content via Ajax, the crawler will not wait for you to finish.” Jump to quote » (Traduction) (Résumé en français de la section soixante-quinze, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- “If you’re only investigating SSR to improve the SEO of a handful of marketing pages … then you probably want SSG instead of SSR.” Jump to quote » (Traduction) (Résumé en français de la section soixante-quinze, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
Vue Router — history mode
«- On hash mode: “It does however have a bad impact in SEO.” Jump to quote » (Traduction) (Résumé en français de la section soixante-dix-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Google — JavaScript SEO basics
«- On canonicals: “The best way to set the canonical URL is to use HTML, but if you have to use JavaScript, make sure that you always set the canonical URL to the same value as the original HTML.” 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.)
Google — dynamic rendering (deprecated)
«- “Dynamic rendering was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines.” Jump to quote » (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.)
Remarque: le wording attributed à John Mueller on SPA rendu échecs, et Martin Splitt appel SSR a “lifesaver,” sont relayed via secondary coverage (Moteur de recherche Land / Moteur de recherche Journal) plutôt que a verified verbatim source, donc ils sont paraphrased ci-dessus plutôt que quoted. Confirmer contre le original talk/transcript avant treating soit as a direct citation.«## Vue SEO checklist » (Traduction) (Résumé en français de la section quatre-vingt-cinq, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«A pass to confirm a Vue 3 app is crawlable and indexable: » (Traduction) (Résumé en français de la section quatre-vingt-six, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] Vue Router uses createWebHistory() (HTML5 history mode), not
createWebHashHistory().
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] Server has an index.html fallback so direct route hits don’t 404.
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] @unhead/vue is wired up; every page sets its own title, description, and
canonical (not all sharing the default).
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] Open Graph / Twitter Card tags are present (and actually render for social
scrapers — i.e. they’re in the served HTML, not CSR-only).
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] Canonical is set in HTML where possible; if injected via JS, it matches.
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] SEO-critical content is in the HTML via SSR/SSG/prerender — not fetched in
onMounted on a CSR page.
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie six : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] Client-side not-found states return a real 404 or a noindex (no soft-404
shells).
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie sept : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] JavaScript and CSS are not blocked in robots.txt.
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie huit : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] No dynamic-rendering dependency in new builds (deprecated by Google).
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie neuf : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] Core Web Vitals pass — code splitting, lazy routes, fetchpriority="high"
on the LCP image.
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie dix : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] If SSR/SSG: no hydration mismatches (check the console; use
data-allow-mismatch only for intentional ones).
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie onze : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] Structured data (JSON-LD) confirmed in the rendered HTML via URL Inspection.
» (Traduction) (Résumé en français de la section quatre-vingt-sept, sous-partie douze : le texte source est conservé pour vérification lors de la relecture francophone.)
The mental models
1. Le par défaut est le trap. Vue 3 out de le box est CSR — contenu n’est pas dans le raw HTML. Tout dans Vue SEO est à propos de overriding que par défaut pour pages que besoin à être trouvé.
2. Rendu decides le résultat.
Le unique highest-leverage choice est comment le HTML est produced: CSR (risky) →
prerender/vite-ssg (contenu-stable) → SSR/SSG via Nuxt (dynamic, SEO-critical).
Pick le lightest option que puts votre contenu dans le HTML.
3. Synchronous dans le HTML, pas async après mount. Contenu c’est là synchronously renders reliably; données récupéré après mount peut être missed — par le robots d’exploration que rendre late, et entirely par le ones que ne pas.
4. Deux audiences de bots. Google renders (eventually). Bing et social scrapers largely ne pas. Design pour le pire un si Bing trafic or share previews matter — que signifie HTML, pas CSR.
5. Le arbre de décision pour a nouveau Vue project.
Pure app behind a login? CSR est fine. Contenu-stable marketing/docs/blog? vite-ssg
or VitePress. Dynamic, per-requête, SEO-critical contenu? Nuxt. Jamais reach pour
dynamic rendu or prerender-spa-plugin — les deux sont dead ends dans 2026.
6. Serveur et client doit agree. Hydration mismatch n’est pas simplement a perf nit — c’est a contenu delta entre ce que Google indexé et ce que le utilisateur obtient. Garder le deux renders identical.
Vue SEO — cheat sheet
Router mode
| Mode | URL | SEO |
|---|---|---|
createWebHistory() | example.com/about | Utiliser ce (nécessite server fallback) |
createWebHashHistory() | example.com/#/about | ”Bad impact in SEO” — éviter |
Head / meta libraries
| Library | Status |
|---|---|
vue-meta | Legacy (Nuxt 2 era) |
@vueuse/head | Sunset |
@unhead/vue (useSeoMeta()) | Actuel standard |
Rendering strategies
| Strategy | Quand | SEO risk |
|---|---|---|
| CSR (par défaut) | App pages, behind login | Highest |
vite-ssg prerender | Content-stable SPAs (marketing/docs/blog) | Low |
| SSR (Nuxt) | Dynamic, per-request pages | Low |
| SSG (Nuxt / VitePress) | Content connu at construire temps | Lowest |
prerender-spa-plugin | — | Legacy/unmaintained — don’t |
| Dynamic rendering | — | Deprecated by Google — don’t |
Rapide facts
- Google renders Vue (evergreen Chromium WRS) — mais delayed, et async données peut être missed.
- Bing + social scrapers souvent ne pas exécuter JS — bare CSR = vide share previews.
- Canonicals: HTML premier; JS canonicals fonctionner mais sont riskier.
- Vue 2 est EOL (Dec 2023) — Vue 3 seulement.
How devrait a Vue route render?
Choisir a Vue SEO rendering chemin
Vue SEO mistakes
- Shipping recherche landing pages as a Vite SPA shell. Utiliser Nuxt SSR/SSG or prerendering donc essential contenu est dans source HTML.
- En utilisant hash mode pour public contenu routes. Fragments ne faites pas créer normal serveur URLs. Utiliser history routing avec host fallback configuré correctement.
- Paramètre head balises seulement après client récupère. Generate metadata depuis serveur/construire données via le head integration.
- En utilisant dynamic rendu as le à long terme corriger. Maintain un consistent utilisateur/robot d’exploration rendu chemin au lieu de bot-spécifique sortie.
- Testing seulement avec Google. Raw HTML matters à autre moteur de recherches, social scrapers, et outils que ne faites pas execute le application entièrement.
Raw HTML contient seulement the Vue mount element
Probable causer: le route est CSR-seulement. Corriger: déplacer il à Nuxt SSR/SSG or prerender le finite route définir. Confirmer: curl renvoie le principal contenu et liens.
Direct route requêtes retourner 404
Probable causer: Vue Router history mode lacks serveur fallback or le deployment omitted generated routes. Corriger: configurer host rewrites pour SPA-seulement routes or deploy réel SSR/static route sortie. Confirmer: refresh et direct requêtes retourner le prévu status et page.
Titles mettre à jour in le navigateur but pas in source
Probable causer: metadata dépend on client lifecycle or an asynchronous navigateur récupérer. Corriger: resolve données during SSR/SSG et rendre head balises avec @unhead/vue or Nuxt’s head APIs. Confirmer: raw et rendu titles, canonicals, et robots directives agree.
Hydration remplace correct serveur contenu
Probable causer: serveur/client données or environment branches disagree. Corriger: faire initial données deterministic et supprimer navigateur-seulement conditions depuis essential markup. Confirmer: hydration completes sans mismatch warnings or modification indexable contenu.
Comparer Vue raw et rendu sortie
curl -fsSL https://example.com/page/ > raw.html
grep -Eio '<title>[^<]+|<h1[^>]*>[^<]+|<link[^>]+rel="canonical"[^>]*' raw.html Run ce in DevTools Console après hydration:
({title: document.title, h1: document.querySelector('h1')?.textContent.trim(), canonical: document.querySelector('link[rel="canonical"]')?.href, links: [...document.querySelectorAll('a[href]')].length});Si le important valeurs exist seulement dans le Console résultat, SSR/prerendering est incomplete.
Trouver hash-based content liens
[...document.querySelectorAll('a[href^="#"]')].map(a => ({text: a.textContent.trim(), href: a.getAttribute('href')}));Examiner the liste manually: in-page navigation is fine; en utilisant fragments as separate content routes is the problem.
Outils pour Vue SEO
- Inspection d’URL (Recherche Google Console) — le source de truth. Exécuter a actif tester et vérifier le rendu HTML, screenshot, page resources (était quelconque JS/CSS bloqué?), et console messages. Ce est comment vous confirmer votre Vue contenu, meta, et JSON-LD en réalité rendu.
- Résultats enrichis Tester — a rapide rendu-HTML + structured-données vérifier pour a unique URL sans verifying le site.
- Chrome DevTools — diff View Source (raw HTML, ce que a non-rendu bot voit) contre le Elements panel (le hydrated DOM). Le Console surfaces hydration mismatch warnings.
- Vue Devtools — inspect component state et router mode pendant que vous debug qu’est-ce que client-seulement vs. serveur-rendu.
vite-ssg— construire-time prerendering pour contenu-stable Vue 3 SPAs (swapvite build→vite-ssg build).- JavaScript-rendu robots d’exploration — Ahrefs Site Audit et Screaming Frog (JS-rendu mode) execute le JS donc vous pouvez diff raw vs. rendu à travers le entier Vue site.
- Lighthouse / PageSpeed Insights — catch le CSR bundle’s hit on LCP et le Core Web Vitals levers (code splitting, lazy routes, image priority).
Testez vos connaissances: Vue SEO
Five rapide questions on making Vue apps crawlable et indexable. Pick an réponse pour chaque, alors vérifier.
Ressources utiles
Mon writing
- JavaScript SEO: A Definitive Guide — mon complet guide à rendu, DOM parity, et le framework-level decisions; inclut le Vue Router history-vs-hash guidance et mon JS-canonical tester.
- Le Beginner’s Guide à SEO technique — où rendu et JavaScript SEO fit 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.”)
Depuis autour le industry
- Rendu côté serveur (SSR) | Vue.js — le official guide: SSR’s SEO avantage, le async caveat, et quand à pick SSG à la place.
- Différent History modes | Vue Router — pourquoi hash mode hurts SEO et comment configurer history mode.
- useSeoMeta() · Unhead — le actuel
@unhead/vuemeta API. - antfu-collective/vite-ssg | GitHub — construire-time prerendering pour Vue 3 SPAs.
- Site Config | VitePress — SEO pour Vue-powered documentation sites.
- Comment Nuxt.js solves le SEO problèmes dans Vue.js | LogRocket — le cas pour Nuxt as le SSR/SSG chemin.
- Google ne … plus recommends en utilisant dynamic rendu | Moteur de recherche Land — coverage de le dynamic-rendu deprecation.
- Vue.js Et SEO: Comment Optimize Reactive Sites web | Smashing Magazine — a widely-cited 2019 piece; utile pour le async-timing experiments, mais dated on tooling (pre-evergreen Chromium).
Videos
- SEO technique tips pour Vue.js par Martin Splitt (Recherche Google Central, 2019) — Google’s propre Vue-spécifique JavaScript SEO episode: making titles, descriptions, et URLs discoverable quand vous construire avec Vue. Watch
- Recherche Google Central (YouTube) — Martin Splitt’s broader JavaScript SEO series covers rendu, le rendre queue, et le échec modes que appliquer à quelconque Vue app. 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.
-
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.