Hướng dẫn về Vue SEO

Vue 3 defaults để client-side kết xuất, so đó nội dung không trong đó thô HTML. Này là cách làm Vue apps crawlable và indexable — router chế độ, @unhead/vue, prerendering với vite-ssg, SSR/SSG với Nuxt, hydration, và Core Web Vitals.

Xuất bản lần đầu: 26 thg 6, 2026 · Cập nhật lần cuối: 8 thg 8, 2026 · Advanced
Ngôn ngữ

Vue 3 defaults để client-side kết xuất, so một đơn giản Vite + Vue app ships an empty HTML shell và xây dựng đó trang trong đó trình duyệt. Google có thể render điều này — nhưng kết xuất là delayed và async dữ liệu có thể là missed, và Bing và social scrapers thường không thể chạy đó JS tại all. Đó các cách sửa: dùng Vue Router history chế độ (không hash chế độ), manage <head> với @unhead/vue, và put nội dung trong đó HTML với prerendering (vite-ssg), SSR, hoặc SSG qua Nuxt. Dynamic kết xuất là deprecated — không xây dựng on điều này.

TL;DR — Vue 3 là CSR theo mặc định, so đó nội dung không trong đó thô HTML — Google renders điều này sau đó qua của nó evergreen Chromium WRS, nhưng đó render là queued và async dữ liệu fetched trong onMounted có thể là missed, và Bing/social scrapers thường không chạy đó JS tại all. Non-negotiables: Vue Router createWebHistory() (hash chế độ có “a bad impact in SEO” (bản dịch) «một bad impact trong SEO»), <head> qua @unhead/vue / useSeoMeta(), và một kết xuất strategy đó nhận nội dung vào HTML — vite-ssg prerendering cho nội dung-ổn định các trang, Nuxt cho đầy đủ SSR/SSG. Dynamic kết xuất là deprecated; prerender-spa-plugin là legacy. Watch hydration mismatches (một máy chủ/client nội dung delta là an SEO vấn đề, không chỉ một perf một) và đó CSR bundle hit on LCP. Cho đó framework-agnostic version of toàn bộ điều này, see JavaScript SEO.

default Vite + Vue scaffold là client-side được kết xuất

đơn giản npm create vue@latest app (Vite + Vue) ships near-rỗng HTML shell và JavaScript bundle. trình duyệt executes đó bundle để xây dựng DOM. Đây là fine cho người dùng và vấn đề cho các crawler: thô HTML contains gần như không nội dung, và mọi thứ phụ thuộc vào kết xuất.

đó thuộc tính của default scaffold, không ceiling on Vue itself — Vue cốt lõi cũng hỗ trợ máy chủ kết xuất (createSSRApp) và static generation as đầu tiên-class paths, và Vue own SSR hướng dẫn steers phần lớn production SSR/SSG hoạt động toward Nuxt thay vì hand-rolled setup. So trước khi reaching cho khắc phục, kiểm tra Điều gì của bạn app là thực ra shipping: bare Vite SPA với không kết xuất config là CSR; giống nhau app behind Nuxt hoặc vite-ssg không phải.

Vue own SSR hướng dẫn là trực tiếp về đó upside of không đang làm này: với máy chủ-side kết xuất, “the search engine crawlers will directly see the fully rendered page.” (bản dịch) «đó công cụ tìm kiếm các crawler sẽ trực tiếp see đó fully được kết xuất trang.» Đó flip side là điều gì bạn ship theo mặc định — nội dung đó chỉ tồn tại sau JavaScript chạy. Evidence for this claim Vue server-side rendering sends rendered HTML so crawlers can directly see page content. Scope: Vue SSR benefits; does not guarantee indexing. Confidence: high · Verified: Vue: SSR guide

(Vue 2 reached end của life trong December 2023; mọi thứ ở đây là Vue 3.)

Cách Googlebot xử lý Vue app

Google xử lý JavaScript trong phases — crawl thô HTML, sau đó render nó trong evergreen, headless Chromium instance ( Web Kết xuất Service), sau đó chỉ mục được kết xuất kết quả. Hai điều follow từ đó:

  • Kết xuất là queued và delayed. MỘT trang sits trong đó render queue — thường seconds để minutes, nhưng điều này có thể spike. Nội dung đó tồn tại chỉ sau JS chạy là không immediately indexable; nội dung trong đó thô HTML là.
  • Async dữ liệu là đó real risk. Synchronous JavaScript renders reliably. Dữ liệu fetched từ an API sau mount không phải guaranteed để là caught. Vue SSR hướng dẫn says điều này plainly: “If your app starts with a loading spinner, then fetches content via Ajax, the crawler will not wait for you to finish. This means if you have content fetched asynchronously on pages where SEO is important, SSR might be necessary.” (bản dịch) «Nếu của bạn app bắt đầu với một loading spinner, thì fetches nội dung qua Ajax, đó crawler sẽ không chờ cho bạn để finish. Này có nghĩa là nếu bạn có nội dung fetched asynchronously on các trang nơi SEO là quan trọng, SSR có thể là necessary.» Practically: dữ liệu fetched trong onMounted là client-chỉ và invisible để các crawler đó không render — và tại risk ngay cả với đó ones đó làm.

John Mueller có described thất bại chế độ cho SPA-style setups nơi static HTML là mostly giống hệt và all unique nội dung phụ thuộc vào JavaScript: nếu đó JS có thể’t là executed properly, các trang end lên looking giống nhau để Google, và focus vẫn giữ on boilerplate HTML thay vì JS-loaded nội dung. lesson là giống nhau as rộng hơn JavaScript SEO trang: nhận nội dung vào DOM, fast và reliably.

Bing và social bots là tệ hơn tại điều này hơn Google. Bing có không kết xuất pipeline comparable để Google, và social preview scrapers (X, Slack, iMessage) generally không chạy JavaScript tại all — so bare CSR Vue app produces rỗng share previews. nếu Bing traffic hoặc social sharing matters, prerendering hoặc SSR không phải tùy chọn.

Vue Router: sử dụng createWebHistory(), không hash chế độ

Vue Router có hai history modes. Hash chế độ (createWebHashHistory()) produces URLs như example.com/#/about; Vue Router tài liệu chẳng hạn điều này “does however have a bad impact in SEO” (bản dịch) «làm tuy nhiên có một bad impact trong SEO» vì mọi thứ sau đó # là một fragment đó máy chủ bỏ qua. Evidence for this claim Vue Router hash history uses a URL fragment that is not sent to the server and is discouraged for SEO. Scope: Vue Router hash history. Confidence: high · Verified: Vue Router: History modes Dùng HTML5 history chế độ:

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [/* ... */],
})

History chế độ cho sạch các URL (example.com/about) nhưng requires máy chủ fallback — bất kỳ trực tiếp yêu cầu để route có để phục vụ index.html so Vue có thể take over, nếu không trực tiếp hits 404. Configure đó catch-all on của bạn host (Nginx try_files, SPA rewrite on Netlify/Vercel/Cloudflare, etc.).

Phạm vi đó rewrite cẩn thận — catch-all đó cũng rộng cũng phục vụ index.html cho bị thiếu static assets, thực API routes, hoặc các trang bạn thực ra muốn để 404. đó silently undoes soft-404 hướng dẫn dưới và có thể hide hỏng link behind trang đó looks như nó “worked.”

cho genuine không-tìm thấy trạng thái, tránh soft-404s — client-side “không tìm thấy” view đó vẫn trả về 200 có thể nhận được lập chỉ mục as rỗng shell. Google hướng dẫn là để either chuyển hướng để URL đó trả về thực 404 status hoặc thêm <meta name="robots" content="noindex"> để lỗi các trang, và để sử dụng History API cho routing giữa views.

Head và meta management: @unhead/vue

theo mặc định mỗi Vue route chia sẻ một <title> và một mô tả meta. tag history ở đây matters vì old các câu trả lời là dead ends:

  • vue-meta — Nuxt 2-era library. Legacy.
  • @vueuse/head — của nó successor, hiện tại sunset.
  • @unhead/vue — hiện tại community tiêu chuẩn, và Điều gì bạn nên sử dụng cho non-Nuxt Vue 3 app.

ergonomic entry point là useSeoMeta() composable — loại-safe, XSS-safe, và aware của 100+ meta tags including Open Graph và 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 có thể là reactive — truyền một getter hoặc computed giá trị và đó tags cập nhật khi của bạn dữ liệu làm. Cho canonical tags, đó safest pattern là vẫn HTML, không JS: Google hướng dẫn là đó “the best way to set the canonical URL is to use HTML,” (bản dịch) «đó best way để set đó canonical URL là để dùng HTML,» và nếu bạn phải inject điều này với JavaScript, luôn set điều này để đó giống nhau giá trị đó HTML sẽ. (I tested JS canonicals tại Ahrefs và được tìm thấy Google làm respect them — điều này ngay cả led Google để thêm an exception để của nó tài liệu — nhưng HTML là vẫn đó thấp hơn-risk path.)

Pick kết xuất strategy

Đây là decision đó thực ra moves needle. giống nhau menu as framework- agnostic JavaScript SEO trang, applied để Vue.

Client-side kết xuất (CSR) — default, và risky một. Acceptable cho app-như các trang behind login, dashboards, và bất cứ điều gì bạn không cần được lập chỉ mục. không acceptable cho nội dung đó phải xếp hạng hoặc là shared.

Prerendering với vite-ssg. cho nội dung-ổn định Vue 3 SPAs, vite-ssg generates static HTML tại xây dựng time — đổi của bạn xây dựng script từ vite build để vite-ssg build. nó ships @unhead/vue được xây dựng trong. Great cho marketing các trang, tài liệu, và blogs; không substitute cho SSR on highly dynamic, theo-yêu cầu các trang. Note đó old webpack-era prerender-spa-plugin là legacy và effectively unmaintainedvite-ssg (hoặc Nuxt) là modern replacement.

Máy chủ-side kết xuất. Vue chính thức hướng dẫn covers một manual SSR setup với @vue/server-renderer, nhưng điều này explicitly steers hầu hết projects để một meta-framework thay vì rolling của bạn own — và cho đơn giản cases điều này ngay cả 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.” (bản dịch) «nếu bạn là chỉ investigating SSR để improve đó SEO of một handful of marketing các trang … thì bạn probably muốn SSG thay vì SSR.» Nếu bạn làm roll manual SSR, tạo đó app, router, và store fresh theo yêu cầu: on một dài-đang chạy Node máy chủ, module-cấp độ singletons nhận reused trên các yêu cầu, và mutating shared state với một người dùng dữ liệu có thể leak điều này vào một sản phẩm khác người dùng phản hồi. đó là một hơn reason Vue tài liệu point hầu hết projects tại Nuxt, mà xử lý theo-yêu cầu isolation cho bạn.

Evidence for this claim Module-scope singleton state in Vue SSR can leak user-specific data across requests; create application, router and store instances per request. Scope: SSR and hydration Confidence: high · Verified: Server-Side Rendering

Nuxt — được khuyến nghị đầy đủ giải pháp. Nuxt cho bạn SSR và SSG out của box, được xây dựng-trong useSeoMeta() và head management, và @nuxtjs/seo module cho sitemaps, robots.txt, và dữ liệu có cấu trúc. cho phần lớn Vue projects nơi SEO matters, Đây là path Vue own tài liệu point để. (Nuxt có của nó own depth — covered riêng; treat điều này as cross-link, không deep dive.)

Dynamic kết xuất — không. Serving prerendered HTML để bots và SPA để người dùng là luôn workaround, và Google deprecated nó trong 2024, removing implementation tài liệu. Xây dựng on SSR hoặc SSG thay vì.

cho tài liệu cụ thể, VitePress là Vue-native static trang web generator. mỗi trang ships as đơn giản HTML — không JS kết xuất barrier — và SEO là configured qua frontmatter (title, description, head) hoặc transformHead xây dựng hook cho canonical/dynamic tags.

Hydration mismatches là SEO vấn đề, không chỉ perf một

Khi bạn làm SSR/SSG, client mounts với createSSRApp() — không đơn giản createApp() — và hydrates máy chủ-được kết xuất HTML thay vì rebuilding nó từ scratch. nếu máy chủ HTML và client render diverge, Vue discards và re-renders mismatched nodes. trong SEO terms, đó có nghĩ là nội dung Google được lập chỉ mục từ máy chủ render có thể differ từ Điều gì người dùng sees sau khi hydration — quality-tín hiệu inconsistency, không chỉ flicker. phổ biến gây ra: không hợp lệ HTML nesting, random các giá trị trong templates, và date/time discrepancies giữa máy chủ và client. Vue 3,5+ adds data-allow-mismatch để suppress mismatch warning selectively nơi khác biệt là intentional — nó quiets console, nó không làm máy chủ và client output tương đương, so không reach cho nó chỉ để silence mismatch bạn haven’t thực ra diagnosed.

Core Web Vitals là Vue-cụ thể concern

Default CSR Vue ships lớn JS bundle đó có để download, parse, và execute trước khi largest nội dung paints — so LCP suffers nếu bạn làm không có gì. Levers:

  • Code splitting (Vite default) và lazy-loaded routes so bạn không ship toàn bộ app lên front.
  • fetchpriority="high" on LCP hero image.
  • Vapor Chế độ — opt-trong compiler chế độ đó bypasses virtual DOM cho eligible components, mà có thể cut hydration cost on SSR các trang. nó Vue 3,6, không 3,5 — vẫn experimental (beta/phát hành-candidate as của mid-2026, không tuy vậy trong ổn định 3,5.x line) — worth watching, không điều gì đó để phụ thuộc on trong production hôm nay.

Dữ liệu có cấu trúc trong Vue

Google executes JavaScript trước khi reading dữ liệu có cấu trúc, so injecting JSON-LD hoạt động — @unhead/vue’s useHead() với script của loại application/ld+json là reliable pattern. vì nó phụ thuộc vào kết xuất, xác nhận nó với URL Inspection thay vì assuming Google saw nó.

nơi điều này fits

Vue SEO là một instance của chung JavaScript SEO vấn đề — parity, interaction, state, timing — và nó chia sẻ gần như mọi thứ với headless CMS situation, nơi kết xuất chế độ của frontend decides outcome.

Một caveat đó áp dụng để mỗi option trên: SSR và SSG nhận của bạn nội dung vào HTML, nhưng neither bảo đảm lập chỉ mục, thứ hạng, Core Web Vitals, hoặc đó hydration sẽ match máy chủ output chính xác. họ xóa JavaScript-kết xuất barrier — rest của SEO (và correctness) là vẫn on bạn.

nếu bạn remember một điều: nhận của bạn nội dung vào HTML. Mọi thứ khác là detail.

Add an expert note

Pin an expert quote

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