DomainLens

Гайди

Vue SPA SEO Checklist: Rendering, Routing & Hydration

A Vue app can be searchable, but an app shell plus asynchronous content creates extra failure points. This checklist tests what arrives before and after hydration.

Перевір сайт перед виправленнями

Запусти свіжий аудит DomainLens і використовуй звіт як список пріоритетів.

Запустити безкоштовний SEO-аудит

Classify routes before choosing SSR for everything

This route inventory prevents two expensive mistakes: building SSR for private application screens that do not need it, and leaving revenue/content routes dependent on a crawler executing several API calls.

Route typeSearch requirementPreferred delivery
Marketing/contentMust be discoverable and indexableSSR or static generation with hydration
Product/categoryIndexable when inventory/content is usefulSSR/SSG with correct status and canonical
Account/dashboardPrivate and not indexableClient rendering is usually fine
Internal search/filter stateUsually not a landing pageControlled URLs and noindex where appropriate
Not foundMust disappear from searchServer 404, not a 200 SPA component

Require useful HTML in the first response

Vue’s SSR guide describes server-rendering components to HTML and hydrating them on the client. For an indexable route, view source should already contain the main heading, primary copy, canonical links, and crawlable navigation.

A click handler on a div, a button that calls router.push, or a link created only after an intersection observer fires is not equivalent to a stable anchor with an href. Use router links for navigation and reserve buttons for actions.

Crawler-discoverable navigation
<RouterLink :to="{ name: 'product', params: { slug: product.slug } }">
    {{ product.name }}
</RouterLink>

Make route metadata deterministic on server and client

  • Resolve the route’s data before SSR so title and canonical do not describe a loading state.
  • Emit one title, description, robots directive, canonical, and social preview; remove duplicates left by the base HTML shell.
  • Use a production base origin and normalized route, not window.location inside server code.
  • Reset head state on navigation so metadata from the previous route cannot leak.
  • Return noindex only for genuinely excluded states; Google may skip rendering a page that starts with noindex.

Handle status codes before Vue mounts

The server or edge layer must know whether a requested entity exists, moved, is private, or failed. Rendering a NotFound.vue component inside an HTTP 200 response creates a soft 404. Rendering an error message after a failed API call can also leave the original title and canonical attached.

StateHTTP responsePage handling
Entity exists200Indexable according to content policy
Slug moved301/308Redirect before app render
Entity removed404 or 410Useful error UI, no canonical to another unrelated page
Authentication required401/403 or login redirectNoindex private shell
Temporary upstream failure5xxDo not disguise as an empty 200 page

Treat hydration mismatch as an SEO defect

Hydration replaces or patches server markup when the client computes different output. Common causes include timestamps, random IDs, browser-only conditions, locale/timezone differences, invalid nesting, and data fetched twice with different results. A page can look acceptable after recovery while wasting main-thread time or replacing the exact text a crawler received.

  1. 1Run the production SSR bundle and watch browser/server logs for hydration warnings.
  2. 2Compare view source, the DOM with JavaScript disabled, and the hydrated DOM.
  3. 3Serialize the server-fetched state and reuse it during hydration instead of immediately refetching.
  4. 4Move browser-only personalization behind onMounted without changing essential indexable content.
  5. 5Test direct entry, client navigation, refresh, slow API, and missing entity cases.

Control crawl space and performance

  • Generate sitemap entries only for canonical public routes backed by real content.
  • Do not create crawlable URLs for every client-side filter combination unless each is a planned landing page.
  • Code-split by route, but preload only critical route assets; excessive hydration JavaScript can hurt INP.
  • Reserve dimensions for async components and media to prevent CLS.
  • Keep the LCP element in SSR output and ensure its image request is discoverable without waiting for the app bundle.

Verify a Vue route with DomainLens and Search Console

Run DomainLens on direct production URLs to check status, rendered metadata, headings, links, indexability, and performance. Then use Search Console’s live test to compare Google’s rendered HTML. The broader JavaScript SEO rendering guide provides a source-versus-DOM debugging workflow when the two disagree.

Схожі ресурси