SEO Nuxt

Nuxt ships serwer-side renderowanie by domyślny, ale że's a per-route setting, nie a guarantee — pełny HTML to crawlers tylko on routes że zachować it. renderowanie modes, useSeoMeta(), the @nuxtjs/seo toolkit, hydration i Nitro caveats, Core Web Vitals, i the mistakes że quietly cost you.

Opublikowano po raz pierwszy: 26 cze 2026 · Ostatnia aktualizacja: 3 sie 2026 · Advanced
Języki
1 sygnał dowodowy na tej stronie

Nuxt serwer-renders strony by domyślny, so a route że zachowuje że domyślny gives crawlers a complete HTML document zamiast the empty shell a plain Vue SPA ships — ale it's a per-route setting: routeRules lub a global ssr:fałszywy może flip dowolny route to CSR, so verify the rzeczywisty route zamiast assuming z the framework nazwa. The foundational decision jest renderowanie mode per route — SSR (domyślny), SSG via nuxt generate, lub hybrid route reguły — ponieważ meta znaczniki, schemat, i sitemaps wszystkie come po że. używać useSeoMeta() dla meta, treat Harlan Wilton's @nuxtjs/seo bundle as an optional third-party toolkit (nie Nuxt core) dla robots/mapa witryny/OG/schemat/canonical, nigdy reach dla dynamiczny renderowanie (Google deprecated it), verify hydration/payload i Nitro deployment-preset/pamięć podręczna behavior independently of serwer HTML, i remember że AI-crawler renderowanie contracts vary by provider — SSR/SSG puts treść in raw HTML i maximizes coverage.

TL;DR — Nuxt’s domyślny jest serwer-side renderowanie, so a route że zachowuje że domyślny gets a complete DOM zamiast the empty shell a plain Vue SPA ships — ale że’s a per-route outcome: ssr: false lub a routeRules override może turn dowolny route do CSR lub hybrid, so test the rzeczywisty route, nie the project nazwa. renderowanie strategy jest the foundational decision — SSR (domyślny), SSG (nuxt generate), or hybrid routeRules — ponieważ meta, schemat, i sitemaps wszystkie come po it. używać useSeoMeta() dla meta znaczniki (useHead() dla the rest of the head, serwer-tylko warianty gdy you don’t need reactivity), i treat Harlan Wilton’s @nuxtjs/seo bundle as an optional third-party toolkit dla robots/mapa witryny/OG/schemat/canonical — nie part of Nuxt core, i nie proof jego output jest poprawny until you sprawdzenie it. nigdy używać dynamiczny renderowanie (Google deprecated it). AI-crawler renderowanie varies by provider — SSR/SSG maximizes raw-HTML coverage. Beyond the initial HTML, verify hydration/payload, Nitro deployment presets i buforowanie, i bezpośredni HTTP status independently — serwer HTML alone doesn’t prove dowolny of tamte. The usual JS-SEO reguły nadal apply: rzeczywisty <a href> links, don’t blok JS/CSS, watch wyrenderowany vs. raw HTML.

Nuxt jest Vue’s answer to the SPA problem

Vue, by itself, ships a single-strona application: an HTML shell plus JavaScript że builds the DOM in the przeglądarka. Nuxt jest the meta-framework on top of Vue (running on the Nitro serwer engine in Nuxt 3, z Nuxt 4 following in 2025), i jego whole powód dla existing — z an SEO standpoint — jest że it renders on the serwer by domyślny. każdy strona arrives as a fully-formed HTML document, który jest exactly co Googlebot wants to read bez having to execute JavaScript pierwszy. Plain Vue SEO jest jego own topic z jego own awaria modes; here I’m assuming you’ve picked Nuxt precisely so you don’t mieć to fight the SPA problem.

ten jest the same point I make o JavaScript generally: “dowolny kind of SSR, statyczny renderowanie, i prerendering setup jest going to być fine dla wyszukiwarki. Gatsby, następny, Nuxt, etc., są wszystkie great.” Nuxt’s defaults są pointed the right way. najbardziej Nuxt SEO problems są people turning tamte defaults off, lub layering mistakes on top of them.

renderowanie strategy jest the foundation — decided per route, nie per project

przed meta znaczniki, przed schemat, przed sitemaps, the question że decides everything jest how robi the HTML get produced dla ten specific route? Nuxt documents universal (serwer) renderowanie as the app-wide domyślny, ale że domyślny isn’t a route-level guarantee: a global ssr: false switches the whole app to client renderowanie, i routeRules może assign a różny mode to dowolny URL pattern. “This is a Nuxt app” tells you nothing o how one particular strona renders — you mieć to sprawdź route. Nuxt gives you five strategies:

ModeHow you ustawić itSEO impactBest dla
Universal / SSRdomyślny (ssr: true)Excellent — pełny HTML każdy żądaniedynamiczny, personalized treść
statyczny / SSGnuxt generateExcellent — HTML built at deploy timeBlogs, docs, marketing
HybridrouteRules per routeExcellent — mix per routeduży mixed-treść witryny
SPA / CSRssr: falsePoor dla zindeksowany treśćpanele, admin panels
Edge-sideDeployment targetExcellent — niski TTFBGlobal wydajność

The official Nuxt docs są blunt o why client-side renderowanie jest the błędny choice dla treść: “indeksowanie i updating the treść delivered via client-side renderowanie takes więcej time”, whereas with server (universal) rendering “web crawlers może directly index the strona’s treść.” Evidence for this claim Nuxt documents that universal rendering delivers HTML content immediately and allows crawlers to index it directly. Scope: Nuxt rendering; no indexing guarantee. Confidence: high · Verified: Nuxt: Rendering modes (Nuxt renderowanie docs.) CSR (ssr: false) jest positioned dla back-office, panele, i games — nie anything you want zindeksowany.

Hybrid renderowanie jest the power move dla duży witryny. Route reguły in nuxt.config.ts let you ustawić the renderowanie i buforowanie mode per URL pattern:

routeRules: {
  '/blog/**':     { prerender: true },        // SSG for the blog
  '/product/**':  { swr: 3600 },              // ISR-style: regenerate hourly
  '/admin/**':    { ssr: false },             // SPA for the admin area
  '/checkout/**': { ssr: true },              // always-fresh SSR
}

swr (stale-podczas gdy-revalidate) i isr (incremental statyczny regeneration) generate a strona statically then refresh it in the background — ideal dla wysoki strona-count e-handel lub news gdzie a pełny rebuild on każdy change isn’t practical. Nuxt Islands (<NuxtIsland>) render components bez wysyłka client-side JavaScript, cutting hydration cost i helping INP — the Core Web Vital że’s najbardziej często the problem on Nuxt apps.

How to verify co you actually shipped: View źródło pokazuje the raw HTML the serwer sent; if twój treść jest there, you’re serwer-renderowanie. DevTools’ elementy panel pokazuje the wyrenderowany DOM. i GSC’s URL Inspection narzędzie pokazuje co Google actually fetched i wyrenderowany — the źródło of truth. Don’t trust “it looks fine in my przeglądarka.”

How Googlebot handles a Nuxt app

Google procesy dowolny JavaScript app in three phases — crawl, render, index — i the catch jest timing: renderowanie happens in a queue, nie instantly. As I put it in my SEO JavaScript poradnik, the renderer jest patient — “there jest no fixed timeout dla the renderer… It’s really patient, i you powinien nie być concerned.” ale patient isn’t the same as fast dla fresh treść. If you ship a client-wyrenderowany strona, twój treść doesn’t exist dla Google until że render wave runs; SSR i SSG close że gap ponieważ the HTML jest complete on the pierwszy fetch.

Two więcej things matter at scale. renderowanie JavaScript jest expensive — z my 2019 SEO JavaScript talk (Ungagged), crawl costs go up by roughly 20× once Google ma to render (directional, ale the order of magnitude nadal holds). i Google takes the najbardziej restrictive directive w całym raw i wyrenderowany HTML — so a noindex injected by JavaScript będzie win ponad an index in the raw HTML, i vice versa. A canonical injected via JavaScript jest respected tylko if there’s no canonical in the raw HTML już. zachować twój robots i canonical signals in the serwer-wyrenderowany HTML, który Nuxt robi dla you gdy SSR jest on.

The AI-crawler reality

ten jest the 2026 wrinkle. AI crawlers — GPTBot, ClaudeBot, PerplexityBot, i the rest — generally don’t execute JavaScript at wszystkie. They index the raw HTML i nothing else. So a client-wyrenderowany Nuxt strona jest effectively invisible to AI answer engines. SSR lub SSG isn’t just better dla Google here; it’s the cena of entry dla optymalizacja silników odpowiedzi too. If you want twój treść cited by ChatGPT, Perplexity, lub Claude, it ma to być in the HTML on pierwszy fetch.

Beyond the initial HTML: payload, hydration, i kody stanu

Getting serwer HTML z twój treść in it jest necessary ale nie sufficient — several things może nadal go błędny downstream of że pierwszy odpowiedź, i “I checked View źródło” doesn’t cover them:

  • Payload i hydration. Universal renderowanie wysyła the HTML i a serialized data payload the client używa to hydrate — attach event listeners i pick up gdzie the serwer left off — bez re-pobieranie. serwer HTML looking right doesn’t prove hydration succeeded, że client navigation reproduces the same treść, lub że the payload isn’t stale. If a strona feels fine on pierwszy load ale breaks po a client-side route change, że’s a hydration/payload problem, nie a renderowanie-mode problem.
  • <ClientOnly> i przeglądarka-tylko treść. Wrapping something in <ClientOnly> — common dla przeglądarka-API-dependent widgets — means it’s absent z the serwer odpowiedź even on an otherwise-universal route. If twój main treść, a key link, lub twój meta znaczniki end up inside a client-tylko granica, crawlers i AI bots że tylko przeczytaj raw HTML miss it, regardless of twój renderowanie mode setting. Inspect the rzeczywisty odpowiedź, nie just the renderowanie mode config.
  • kody stanu i redirects aren’t self-certifying. A Nuxt błąd strona renderowanie in the przeglądarka, lub a navigateTo()/composable-driven redirect, doesn’t by itself prove co HTTP status the bezpośredni serwer odpowiedź sent. Google’s guidance jest explicit że meaningful kody stanu matter dla crawling i indeksowanie — confirm the rzeczywisty header z curl -I, nie co the client-wyrenderowany błąd strona displays.

None of ten jest an argument wobec universal renderowanie — it’s the reminder że “the HTML is server-rendered” jest the pierwszy sprawdzenie, nie the ostatni one.

Nitro, deployment presets, i pamięć podręczna granice

Nuxt’s serwer output jest built by Nitro, i Nitro compiles differently depending on the deployment preset you target (Node serwer, Cloudflare, Vercel, Netlify, statyczny, i others). że matters dla SEO ponieważ presets i adapters może differ in runtime APIs available, buforowanie behavior, streaming obsługiwać, regional deployment, i filesystem access — a route reguła lub serwer handler że działa poniżej one preset isn’t guaranteed to behave identically poniżej another. Two consequences worth testing explicitly zamiast assuming:

  • pamięć podręczna keys i invalidation są route-specific, nie automatic. swr i isr route reguły pamięć podręczna i regenerate output, ale a błędny pamięć podręczna key, missing invalidation, lub a buforowanie header ustawić by twój deployment platforma może serve stale, personalized, lub inconsistent HTML to crawlers. sprawdź rzeczywisty odpowiedź age i dowolny Cache-Control/Age headers on a live URL, nie just the routeRules config.
  • Production parity isn’t guaranteed by staging behavior. A route renderowanie correctly in local dev lub a preview deployment doesn’t confirm the production preset produces the same output — serwer routes, redirects, i błąd handling live in Nitro’s serwer warstwa, i że warstwa jest the part najbardziej prawdopodobny to differ by target. Test the production URL directly po dowolny deployment change, the same way you’d verify renderowanie mode.

Meta znaczniki: useSeoMeta() i useHead()

Nuxt’s head management runs on Unhead, i it gives you two composables dla różny jobs.

useSeoMeta() jest the one to reach dla dla SEO i social meta znaczniki. It’s a flat, type-bezpieczny API z typed parametry. Evidence for this claim useSeoMeta is a typed Nuxt API for SEO and social meta tags. Scope: Current Nuxt composable. Confidence: high · Verified: Nuxt: useSeoMeta It pomaga unikaj classic otwarty Graph bug of używając name gdzie you needed property:

useSeoMeta({
  title: 'My Page Title',
  ogTitle: 'My Page Title',
  description: 'Concise page-specific description with the key information first',
  ogDescription: 'Concise social description tailored to this page',
  ogImage: 'https://mysite.com/og-image.png', // must be an absolute URL
  twitterCard: 'summary_large_image',
})

useHead() jest the general-purpose head narzędzie dla everything else — scripts, link znaczniki, body atrybuty, i tytuł templates:

useHead({
  titleTemplate: '%s · My Site Name',
  htmlAttrs: { lang: 'en' },
})

The niezawodny layering pattern jest: statyczny defaults (charset, viewport, favicon) in nuxt.config.ts → witryna-wide tytuł template i global OG defaults in app.vue → strona-specific overrides via useSeoMeta() in the strona component. A common bug jest putting useSeoMeta() in a layout zamiast the strona, który overwrites specific strona znaczniki z generic ones. i since wyszukiwarki przeczytaj initial load, SEO meta generally doesn’t need to być reactive — useServerHead() skips the client-side re-execution.

który API, i co it actually proves:

APIScopeReactive?co it proves o output
useSeoMeta()Flat, typed SEO/social meta tylkoYes (domyślny)ustawia typed właściwości correctly — nie że the route jest unique, canonical, lub indeksowalny; you nadal own że logic
useHead()Anything in <head> — scripts, links, attrs, tytuł templateYes (domyślny)General head control; same caveat — API używać isn’t proof of a poprawny serwer odpowiedź
useServerHead() / serwer-tylko callsSame as aboveNo — serwer tylko, skips client re-executionConfirms the znacznik ships once in serwer HTML; doesn’t confirm client navigation re-ustawia it if you rely on it there

Calling one of te composables tells you the API ran — it doesn’t by itself tell you co a bezpośredni serwer odpowiedź lub a client-side route change actually emits. Confirm z View źródło lub curl, nie just “I called useSeoMeta().”

The @nuxtjs/seo module ecosystem (Harlan Wilton) — optional, nie core

Nuxt core doesn’t ship a mapa witryny, a robots.txt, OG image generation, lub schemat.org out of the box — tamte są outside Nuxt’s own primitives (useHead, useSeoMeta, route reguły, renderowanie modes). The community fills że gap z Harlan Wilton’s @nuxtjs/seo — a osobno-installed, third-party umbrella package (nuxtseo.com, currently at v5.x, actively maintained, targeting Nuxt 3,16+ i Nuxt 4) że bundles six modules. Installing it gives you mapa witryny, robots, OG-image, i schemat generation — it doesn’t by itself guarantee the output jest poprawny dla twój routes; verify co it produces the same way you’d verify anything else:

Moduleco it robi
@nuxtjs/robotsrobots.txt + meta robots + X-Robots-Tag headers
@nuxtjs/sitemapAuto XML sitemaps z strony + dynamiczny routes
nuxt-og-imagedynamiczny OG images (a Vue template → an image)
nuxt-schema-orgschemat.org JSON-LD dane strukturalne
nuxt-seo-utilsCanonical URLs, breadcrumbs, defaults
nuxt-link-checkerBuild-time broken-link detection

Install the whole bundle z npx nuxt module add seo, lub grab individual modules (npx nuxt module add sitemap robots). A kilka behaviors worth knowing:

  • @nuxtjs/sitemap auto-generates z twój pages/ directory plus dynamiczny routes, splits do a mapa witryny index automatically past 50 000 URLs, obsługuje i18n multi-język sitemaps, i ma built-in IndexNow obsługiwać. One thing to get right: Google ignores changefreq i priority; tylko an accurate lastmod matters, i tylko gdy treść genuinely changes.
  • @nuxtjs/robots generates robots.txt, the robots meta znacznik, i the X-Robots-Tag header — i by domyślny it disallows wszystkie crawlers on non-production environments, który jest exactly the staging-indexation footgun że bites headless builds. It również gives you per-bot reguły, so you może blok GPTBot specifically podczas gdy leaving everyone else alone (być intentional — blok an AI crawler i it won’t cite you).
  • nuxt-seo-utils handles canonical URLs i, usefully, strips tracking parametry (utm_*, fbclid, gclid) z canonicals automatically.

nuxt/image i Core Web Vitals

@nuxt/image jest the image module: automatic responsive srcset, modern formaty (WebP/AVIF), built-in optymalizacja przez CDN providers, i lazy ładowanie. Two reguły carry najbardziej of the SEO wartość:

  • nigdy lazy-load the LCP image. twój hero image powinien load eagerly; lazy-ładowanie it opóźnienia twój Largest Contentful Paint.
  • zawsze ustawić width i height so the przeglądarka reserves space i you don’t take a Cumulative Layout Shift hit.
<NuxtImg
  src="/hero.jpg"
  width="1200"
  height="630"
  alt="Descriptive alt text"
  :loading="isHeroImage ? 'eager' : 'lazy'"
  format="webp"
/>

The 2026 targets to aim dla (p75): LCP ≤ 2,5s, INP ≤ 200ms, CLS ≤ 0,1. On Nuxt apps, INP jest the one że tends to suffer ponieważ hydration creates input lag — który jest exactly co Nuxt Islands i <NuxtIsland> są dla.

Nuxt treść + SEO

If you’re używając @nuxt/content (the markdown/MDX treść module), the integracja z @nuxtjs/seo jest straightforward ale ma one ordering gotcha: load @nuxtjs/seo przed @nuxt/content in twój modules tablica. You może then ustawić SEO in treść frontmatter (title, description, robots, ogImage, schemaOrg) i pull it do twój [slug].vue template z useSeoMeta() po pobieranie the treść. ten jest the Nuxt-native version of the headless-CMS pattern, i the same “rebuild co the plugin zrobił” discipline applies.

Common Nuxt SEO mistakes

  1. używając SPA mode (ssr: false) dla treść you want zindeksowany. The najbardziej expensive mistake — i the one że makes you invisible to AI crawlers.
  2. Relative URLs dla OG images. ogImage musi być an absolute URL lub social previews break.
  3. useSeoMeta() in a layout zamiast the strona — generic znaczniki overwrite strona-specific ones.
  4. nie verifying wyrenderowany HTML — View źródło ≠ DevTools ≠ co Google wyrenderowany. używać URL Inspection.
  5. Blocking JS/CSS in robots.txt — Google won’t render z blocked files.
  6. Leaving the staging noindex/disallow in place po launch (lub, conversely, forgetting @nuxtjs/robots bloki non-prod by domyślny i wondering why prod jest fine ale a custom env isn’t).
  7. Lazy-ładowanie the LCP image — tanks twój LCP.
  8. Missing width/height on images — CLS.
  9. changefreq/priority in sitemaps — Google ignores them; tylko lastmod counts.
  10. Reaching dla dynamiczny renderowanie. Google deprecated it — “dynamic rendering is a workaround and not a long-term solution” — i it tylko serves the engines you configure it dla, missing Bing i każdy AI crawler. z Nuxt you nigdy need it: SSR i SSG już give crawlers complete HTML.

llms.txt i AEO

llms.txt jest a plain-tekst file — robots.txt’s cousin — że pomaga AI narzędzia navigate twój treść. The nuxt-llms module auto-generates /llms.txt i /llms-full.txt z Nuxt treść. As of late 2025 jego primary consumers są MCP serwery i AI coding narzędzia (Cursor, Claude Code) zamiast ChatGPT lub Perplexity directly, i it’s najbardziej użyteczny dla documentation witryny i technical blogs — mniej so dla e-handel lub news. Worth adding if you’re a docs/dev witryna; nie a priority otherwise.

gdzie ten fits

Nuxt SEO jest really a concrete application of SEO JavaScript przez Nuxt’s own conventions — i it overlaps heavily z the SEO dla a headless CMS topic gdy twój Nuxt frontend pulls z a headless backend. The principles don’t change; Nuxt just gives you good defaults i a strong module ecosystem to implement them z.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.