Hướng dẫn về SPA SEO

Cách làm single-trang applications (React Router, Vue Router, Angular Router) crawlable và indexable — đó app-shell và soft-404 các vấn đề, History API so với hash routing, theo-route HTML qua SSR/prerendering, theo-route canonicals và các tiêu đề, và sitemap generation cho client-side routes.

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

MỘT single-trang application loads một document và swaps views với JavaScript thay vì requesting một new trang từ đó máy chủ. Nhiều SPAs implement đó với an 'app shell' — đó máy chủ trả về một URL's worth of real HTML, một near-empty shell, until JS renders mỗi route — nhưng đó là một phổ biến implementation lựa chọn, không một rule mỗi SPA follows; kiểm tra điều gì một trực tiếp yêu cầu để mỗi route thực ra trả về trước assuming điều này. Đó cách sửa, nơi một bare app-shell setup là đó vấn đề, có hai independent halves: addressability (History API, không hash/#! fragments, so mỗi view có một real URL — một trình duyệt soft navigation qua đó History API thay đổi đó URL và UI nhưng không itself tạo một new máy chủ phản hồi) và nội dung availability (SSR, prerendering, hoặc một meta-framework so mỗi of những URLs có thể trả về unique HTML on yêu cầu). On top of đó, verify mỗi route tiêu đề, canonical, và robots state cả hai on trực tiếp entry và sau kết xuất, xử lý soft 404s (routers tend để giữ một 200 status cho 'không tìm thấy' views — chuyển hướng để một URL đó itself 404s, hoặc thêm một được kết xuất noindex, though an ban đầu noindex có thể nguyên nhân kết xuất để là skipped), và hãy bảo đảm mỗi route trong của bạn sitemap thực ra resolves để real, indexable HTML — có không special SPA sitemap format.

Tóm tắt — SPA cốt lõi SEO risk không phải “JavaScript” trong abstract — nó đó client-side routing thay đổi Điều gì người dùng sees không có thay đổi Điều gì máy chủ sẽ trả về. khắc phục có hai independent halves mọi người constantly conflate: addressability (History API, unique theo-route các URL, không #! fragments) và nội dung availability (SSR, prerendering/SSG, hoặc meta-framework). Làm chỉ đầu tiên và bạn nhận tidy sitemap của các URL đó all render giống nhau shell. bên cạnh cả hai, mỗi route cần của nó own canonical/tiêu đề/mô tả trong được kết xuất DOM, bạn có để xử lý soft 404s đó giữ 200, và mỗi route trong sitemap có để independently resolve để thực HTML.

Điều gì SPA SEO thực ra là

SPA là application architecture, không guaranteed SEO thất bại state. Evidence for this claim Primary standard or official documentation supporting the adjacent article claim. Scope: Protocol semantics and Search behavior are kept separate; no indexing, ranking, or migration-timing guarantee is inferred. Confidence: high · Verified: MDN: Single-page application máy chủ kết xuất, prerendering, hoặc cẩn thận implemented client kết xuất có thể expose nội dung, nhưng none bảo đảm lập chỉ mục. Evidence for this claim Primary standard or official documentation supporting the adjacent article claim. Scope: Protocol semantics and Search behavior are kept separate; no indexing, ranking, or migration-timing guarantee is inferred. Confidence: high · Verified: Google: JavaScript SEO basics

Đây là deep dive on single-trang applications cụ thể — client-side routing với React Router, Vue Router, hoặc Angular Router, nơi sau khi đầu tiên load máy chủ không bao giờ gửi một đầy đủ trang. nó sits alongside rộng hơn JavaScript SEO hướng dẫn (mà covers parity, lazy-loading, infinite scroll, và JS kết xuất generally) và theo-framework ghi-ups cho React, tiếp theo.js, Nuxt, Angular, Vue, Svelte, và Astro. Ở đây I’m chỉ interested trong routing layer và Điều gì nó làm để crawling và lập chỉ mục.

Vì sao bare client-side-routed SPAs fail tại SEO

Một URL, một HTML phản hồi — app-shell vấn đề

Google mô tả đó chế độ lỗi precisely: “Some JavaScript sites may use the app shell model where the initial HTML does not contain the actual content and Google needs to execute JavaScript before being able to see the actual page content.” (bản dịch) «Some JavaScript các trang có thể dùng đó app shell model nơi đó ban đầu HTML không contain đó thực tế nội dung và Google cần để execute JavaScript trước đang able để see đó thực tế trang nội dung.» Trong một bare SPA, đó “app shell” là all đó máy chủ bao giờ trả về. Fetch /products fresh và bạn nhận đó giống nhau near-empty document bạn’d nhận cho /about. Đó nội dung chỉ diverges sau đó trình duyệt chạy của bạn JavaScript và của bạn router decides điều cần cho thấy.

đó toàn bộ vấn đề trong một sentence: client-side routing thay đổi Điều gì người dùng sees không có thay đổi Điều gì máy chủ sẽ trả về. Mọi thứ downstream — soft 404s, duplicate nội dung, bị thiếu các tiêu đề — là symptom của đó.

máy chủ không bao giờ sees mà “trang” là requested (Vì sao hash routing fails)

Older SPAs load views từ URL fragments — example.com/#/products. Google chính xác words: “A SPA may use URL fragments (for example https://example.com/#/products) for loading different views.” (bản dịch) «MỘT SPA có thể dùng URL fragments (ví dụ https://example.com/#/products) cho loading khác nhau views. » Này fails cho một cụ thể, mechanical reason: các trình duyệt không bao giờ gửi đó fragment (bất cứ điều gì sau #) để đó máy chủ trong đó HTTP yêu cầu. Đó máy chủ theo nghĩa đen không thể know mà “trang” đã là requested, so điều này không thể trả về khác nhau nội dung hoặc một khác nhau mã trạng thái cho điều này. MỘT crawler đó fetches đó URL khi nhận giống hệt HTML regardless of đó fragment.

đó là cũng vì sao Google formally deprecated của nó 2009 AJAX-crawling scheme lại trong October 2015: “In short: We are no longer recommending the AJAX crawling proposal we made back in 2009.” (bản dịch) «Tóm lại: We là không lâu hơn recommending đó AJAX crawling proposal we đã làm lại trong 2009.» Đó old _escaped_fragment_ workaround let các máy chủ pre-render fragment routes on yêu cầu — nhưng điều này patched khoảng đó routing vấn đề thay vì sửa điều này. Google own khuyến nghị thay thế điều này là đó History API, covered dưới.

Soft 404s — client-side routers giữ 200 cho mọi thứ

Này một là close để inevitable trong một bare SPA. Client-side routers, by design, giữ đó original trang 200 status cho mỗi virtual navigation — including “không tìm thấy” trạng thái. Google flags điều này explicitly: “In a single-page application (SPA), this can be especially difficult. To prevent error pages from being indexed, you can use one or both of the following strategies.” (bản dịch) «Trong một single-trang application (SPA), này có thể là especially difficult. Để ngăn lỗi các trang từ đang được lập chỉ mục, bạn có thể dùng một hoặc cả hai of đó sau strategies.» Và đó vì sao: “When a SPA is using client-side JavaScript to handle errors they often report a 200 HTTP status code instead of the appropriate status code.” (bản dịch) «Khi một SPA là dùng client-side JavaScript để xử lý các lỗi they thường báo cáo một HTTP mã trạng thái thay vì đó appropriate mã trạng thái.»

kết quả là rỗng hoặc lỗi views getting được lập chỉ mục as thin 200 các trang. Google documents chính xác hai strategies ở đây, precisely: chuyển hướng (hoặc làm đầy đủ yêu cầu) để URL whose máy chủ trả về thực 404/lỗi status, hoặc thêm noindex tag để lỗi view với JavaScript. Watch thứ hai một: nếu đó noindex là present từ rất đầu tiên paint thay vì đã thêm sau khi app decides route là không hợp lệ, nó có thể nguyên nhân Google để skip kết xuất trang altogether — so verify Điều gì trực tiếp yêu cầu trả về trước khi bất kỳ JS chạy, không chỉ Điều gì hiển thị lên trong được kết xuất DOM afterward.

Evidence for this claim For a client-rendered not-found view, Google documents two approaches: redirect to a URL whose server returns a 404 response, or add noindex with JavaScript; an initial noindex can cause rendering to be skipped, so raw and rendered directives require separate testing. Scope: SPAs Confidence: high · Verified: Fix Search-related JavaScript problems

Shared-shell duplicates — có thể nguyên nhân, không tự động diagnosis

có một second, sneakier chế độ lỗi: distinct routes nhận được lập chỉ mục as duplicates of mỗi other vì they render xuống để đó giống nhau shared header/nav/footer boilerplate. Gary Illyes described một way này happens: “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.” (bản dịch) «I có một bunch of emails trong my inbox nơi đó vấn đề là đó centerpiece took forever để load, so kết xuất timed out (my hầu hết có khả năng lời giải thích) và we đã là left với một bunch of các trang đó chỉ đã có đó boilerplate. Với chỉ đó boilerplate, những các trang là dups.» His cách sửa: “Try to restructure the js calls such that the content (including marginal boilerplate) loads first.” (bản dịch) «Try để restructure đó js calls such đó nội dung (including marginal boilerplate) loads đầu tiên.» (Relayed qua một LinkedIn post, mà resists automated verification; treat as cao-confidence phụ.)

Notice Illyes frames điều này as “my most likely explanation,” (bản dịch) «my hầu hết có khả năng lời giải thích,» không một confirmed diagnosis — đó là worth taking theo nghĩa đen. “Render timeout” (bản dịch) «Render timeout» không điều gì đó bạn có thể diagnose từ symptoms alone; bạn cần yêu cầu-cấp độ evidence (điều gì một trực tiếp fetch thực ra trả về), được kết xuất-output evidence (liệu đó centerpiece nội dung là present sau kết xuất), và Search Console evidence (duplicate/các tín hiệu lập chỉ mục) trước attributing một route duplicate-nội dung vấn đề để một timeout cụ thể, thay vì để một bug, một blocked tài nguyên, hoặc một genuinely giống hệt shell. có cũng không fixed, published timeout để design khoảng — Google own basics doc says một trang “may stay on this queue for a few seconds, but it can take longer than that,” (bản dịch) «có thể stay on này queue cho vài seconds, nhưng điều này có thể take lâu hơn đó,» không có committing để một number. không plan khoảng an assumed render-queue duration; thay vì, hãy bảo đảm chính nội dung loads as sớm as có thể regardless of cách dài kết xuất ends lên taking.

khắc phục: nhận thực HTML theo route

đầy đủ khắc phục có hai independent parts đó mọi người conflate constantly:

  1. URL addressability — History API, unique theo-route các URL, không fragments.
  2. nội dung availability — SSR, static prerendering/SSG, hoặc meta-framework.

Làm chỉ #1 và bạn nhận sạch, shareable các URL đó all vẫn trả về giống nhau blank shell. cho route bạn thực ra muốn được lập chỉ mục, bạn cần cả hai.

đó không universal mandate để thêm SSR mọi nơi, though. SSR và prerendering reduce Cách nhiều bạn phụ thuộc on crawler successfully executing của bạn JavaScript — họ không become mandatory instant trang web là technically SPA. trước khi picking architecture cho được cho route, kiểm tra three điều: liệu đó route cần để xếp hạng tại all ( internal admin panel không), Điều gì trực tiếp, JS-free yêu cầu để nó đã trả về (some setups đã gửi có ý nghĩa HTML), và mà các crawler bạn thực ra cần để satisfy (Google renders JS fairly reliably; Bing và phần lớn AI các crawler ít hơn so — see dưới). CSR đó đã truyền những điều đó kiểm tra không cần để become SSR chỉ vì trang web là SPA.

máy chủ-side kết xuất (SSR)

máy chủ chạy của bạn app cho mỗi yêu cầu và trả về fully-formed HTML cho đó route, sau đó client “hydrates” nó vào trực tiếp SPA. Đây là phần lớn robust option vì crawler nhận hoàn tất nội dung on đầu tiên fetch, không JS execution bắt buộc.

Static prerendering / SSG

thay vì kết xuất theo yêu cầu, bạn xây dựng mỗi route HTML ahead của time tại deploy. Perfect cho nội dung đó không thay đổi theo người dùng. từ my own JavaScript SEO writing: bất kỳ kind của SSR, static kết xuất, và prerendering setup là going để là fine Đối với tìm kiếm engines — điều để tránh là leaving nội dung locked behind client-chỉ kết xuất.

hoặc: không hand-roll nó — sử dụng meta-framework

cho new xây dựng, honest khuyến nghị là để không hand-roll React-Router-chỉ hoặc Vue-Router-chỉ client-side routing tại all. meta-framework — tiếp theo.js, Nuxt, Angular với của nó SSR package, SvelteKit, Remix — cho bạn SSR/SSG và route-based metadata out của box, mà sidesteps điều này đểàn bộ category của vấn đề. (mỗi của những điều đó có của nó own deep dive on điều này trang web.) là honest về flip side: retrofitting SSR onto existing hand-rolled SPA là thực engineering hoạt động — migration project, không config toggle.

Dynamic kết xuất as stopgap, không đích

Bạn có thể serve các crawler một riêng-được kết xuất HTML snapshot (dynamic kết xuất). Cả hai Google và Bing accept điều này — Bing “recommend[s] dynamic rendering as a great alternative for websites relying heavily on JavaScript” (bản dịch) «khuyến nghị[s] dynamic kết xuất as một great alternative cho websites relying heavily on JavaScript» (relayed từ Bing 2018 blog; đó hai ngắn bingbot-khả năng quotes dưới là trực tiếp verified, này lâu hơn một không phải independently re-checked) — nhưng Google là clear đây là một workaround: “Dynamic rendering was a workaround and not a long-term solution… Instead, we recommend that you use server-side rendering, static rendering, or hydration as a solution.” (bản dịch) «Dynamic kết xuất đã là một workaround và không một dài-term giải pháp… Thay vì, we khuyến nghị đó bạn dùng máy chủ-side kết xuất, static kết xuất, hoặc hydration as một giải pháp.» (Relayed từ Google dynamic-kết xuất doc; wording matches điều gì là đã cited trong này site rộng hơn JavaScript SEO hướng dẫn.) đây là một bridge, không an architecture.

History API so với. hash routing (#!)

Five trạng thái, không hai

Kiểm thử an SPA route nhận confusing vì “does it work” (bản dịch) «làm điều này hoạt động» thực ra spans five khác nhau, riêng-verifiable trạng thái:

StateĐiều gì nó là
máy chủ phản hồibytes fresh, JS-free HTTP yêu cầu để URL thực ra nhận lại.
Được kết xuất DOMĐiều gì trình duyệt (hoặc Googlebot’s renderer) xây dựng sau khi executing JavaScript so với đó máy chủ phản hồi.
Tìm kiếm processingCách Google riêng crawl máy chủ phản hồi, sau đó renders trang, và indexes dựa trên cả hai.
trình duyệt đầy đủ-document navigationthực tế new HTTP yêu cầu để URL — chỉ state đó có thể thay đổi máy chủ phản hồi hoặc mã trạng thái.
trình duyệt soft navigationHistory API transition (pushState/replaceState) đó thay đổi visible URL, trình duyệt history, và on-screen UI.

một mọi người conflates: soft navigation thay đổi URL và UI, nhưng nó làm không by itself tạo new HTTP phản hồi hoặc status — đó chỉ happens on đầy đủ navigation (hoặc tương đương trực tiếp yêu cầu, như curl). Kiểm thử route by clicking qua app từ homepage exercises soft navigation; kiểm thử nó by requesting URL trực tiếp exercises máy chủ phản hồi. Cả hai quan trọng, và họ có thể disagree.

Điều gì History API cho bạn

Google khuyến nghị là unambiguous: “We recommend using the History API to load different content based on the URL in a SPA.” (bản dịch) «We khuyến nghị dùng đó History API để load khác nhau nội dung dựa trên đó URL trong một SPA.» (Trong đó trực tiếp doc “History API” là một link, so này deep link targets đó lead-trong clause.) Đó History API (pushState/replaceState) lets của bạn router thay đổi đó visible URL để một real, bookmarkable path — /products, không /#/products — không có một đầy đủ reload. Đó các cách sửa đó addressability half: mỗi view hiện tại có một URL một máy chủ có thể respond để differently.

Vì sao fragment/hash các URL là invisible để máy chủ — và để Google

Vì đó fragment không bao giờ reaches đó máy chủ (see trên), đó History API là đó chỉ way để cho mỗi route một URL đó máy chủ có thể thực ra serve. Google diễn đạt một floor dưới điều này trong của nó basics doc: “don’t use fragments to load different page content. The following example is a bad practice, because Googlebot can’t reliably resolve the URLs.” (bản dịch) «không dùng fragments để load khác nhau trang nội dung. Đó sau ví dụ là một bad practice, vì Googlebot không thể reliably resolve đó URLs.» Này là đó giống nhau hướng dẫn I’ve được viết elsewhere — dùng thông thường-looking URLs như /products, không hash URLs như /#/products, vì Google không thể reliably chỉ mục đó hash ones.

2015 deprecation, briefly

Đó hash-bang (#!) era ended với Google 2015 post: “Times have changed. Today, as long as you’re not blocking Googlebot from crawling your JavaScript or CSS files, we are generally able to render and understand your web pages like modern browsers,” (bản dịch) «Times có changed. Hôm nay, miễn là bạn là không blocking Googlebot từ crawling của bạn JavaScript hoặc CSS files, we là generally able để render và understand của bạn web các trang như modern các trình duyệt,»“you can use the History API pushState() to ensure accessibility for a wider range of browsers (and our systems).” (bản dịch) «bạn có thể dùng đó History API pushState() để bảo đảm accessibility cho một wider range of các trình duyệt (và của chúng ta các hệ thống).» Một nuance worth giữ: Google đã không instantly deindex old hash-bang các trang — “we’ll generally crawl, render, and index the #! URLs” (bản dịch) «we’ll generally crawl, render, và chỉ mục đó URLs» — nhưng “we can still try” (bản dịch) «we có thể vẫn try» không phải “you should still do this.” (bản dịch) «bạn nên vẫn làm này.»

Đang làm mỗi route independently indexable

Sạch các URL và thực HTML nhận bạn được crawl. để nhận được lập chỉ mục correctly, mỗi route cần của nó own các tín hiệu.

Theo-route canonical tags — và đó “most restrictive directive” (bản dịch) «hầu hết restrictive directive» trap

mỗi route cần của nó own rel=canonical trong được kết xuất DOM. trap: nếu placeholder canonical (hoặc noindex) ships trong thô HTML shell và JavaScript là supposed để overwrite nó sau đó, Bạn có thể nhận conflict. Google resolves conflicts giữa thô và được kết xuất versions by taking nhiều hơn restrictive tín hiệu — as I’ve put nó trước khi, Google sẽ chọn phần lớn restrictive statements giữa HTML và được kết xuất version của trang. stray noindex hoặc sai canonical baked vào shell có thể silently suppress toàn bộ route ngay cả sau khi của bạn JS “các cách sửa” nó.

Theo-route các tiêu đề và meta các mô tả qua JavaScript

Setting những trong JS là fine — Google says so trực tiếp: “You can use JavaScript to set or change the meta description as well as the <title> element.” (bản dịch) «Bạn có thể dùng JavaScript để set hoặc thay đổi đó mô tả meta cũng như đó thẻ tiêu đề element.» Đó requirement là đó they land trong đó được kết xuất DOM Google evaluates, không chỉ flash briefly. Cho mỗi trang của nó own tiêu đề và mô tả đó cập nhật khi đó route thay đổi.

Làm của bạn inter-route links real anchors với href các thuộc tính, không nhấp handlers on <div>s. Google discovers URLs by extracting hrefs; một <div onClick> đó navigates qua đó router là invisible để đó crawler link extraction. Và không lean on client-side state để carry nội dung trên những navigations — Google renderer “does not retain state across page loads: Local Storage and Session Storage data are cleared across page loads. HTTP Cookies are cleared across page loads.” (bản dịch) «không retain state trên trang loads: Local Storage và Session Storage dữ liệu là cleared trên trang loads. HTTP Cookies là cleared trên trang loads.»

Sitemap generation cho SPA routes

có không special “SPA sitemap” format — nó accounting vấn đề

sitemap giao thức là unchanged cho SPAs. thực tế hoạt động là đang làm sure mỗi route bạn list independently resolves để thực, unique, được kết xuất HTML. sitemap của 500 client-side routes là worthless nếu những điều đó routes all trả về giống nhau shell. So sitemap là downstream của bạn kết xuất strategy, không substitute cho nó.

Xử lý dynamic/parameterized routes (/product/:id)

cho apps với parameterized routes, Bạn có thể’t hand-maintain list. sitemap generator có để chạy so với giống nhau dữ liệu nguồn app dùng — xây dựng script hoặc máy chủ điểm cuối đó enumerates mỗi id — so sitemap và app không bao giờ drift apart. những điều đó enumerated các URL là chỉ worth listing sau khi họ’re SSR’d hoặc prerendered.

Giữ sitemap trong sync với Điều gì máy chủ-resolvable

Regenerate sitemap as part của bạn xây dựng hoặc on schedule tied để của bạn nội dung nguồn. route đó 404s (hoặc tệ hơn, soft-404s tại 200) nhưng sits trong của bạn sitemap là crawl-budget và quality tín hiệu bạn không muốn.

Kiểm thử Điều gì Google thực ra sees

không spot-kiểm tra một URL. toàn bộ point của SPA vấn đề là đó routes có thể differ trong trình duyệt nhưng không on wire, so kiểm thử multiple routes tại thô-HTML cấp độ:

  • Fetch thô HTML theo route với curl ( Googlebot người dùng-agent nơi relevant) và xác nhận nội dung là unique theo URL, không shared shell.
  • URL Inspection trong Search Console — so sánh được crawl/được kết xuất HTML cho several routes, và xác nhận theo-route tiêu đề, mô tả, và canonical là present.
  • xác nhận lỗi routes trả về right tín hiệu — “không tìm thấy” view nên either chuyển hướng để thực lỗi status hoặc carry noindex trong được kết xuất DOM.

phổ biến myths về SPA SEO

  • “Google can’t index SPAs at all.” (bản dịch) «Google không thể chỉ mục SPAs tại all.» Outdated. Google chạy evergreen Chromium và generally renders SPA nội dung. Đó real risks là cụ thể: soft 404s, hash routing, render timeouts, và non-Google các crawler (Bing ít hơn reliably, hầu hết AI các crawler không tại all).
  • “Adding the History API fixes SPA SEO.” (bản dịch) «Thêm đó History API các cách sửa SPA SEO.» Điều này các cách sửa addressability chỉ. Nếu đó máy chủ vẫn trả về đó giống nhau shell cho mỗi route, Google vẫn có để execute JS để see bất cứ điều gì.
  • “Hash routing still works as a fallback.” (bản dịch) «Hash routing vẫn hoạt động as một fallback.» Deprecated since 2015 và được khuyến nghị so với bao giờ since.
  • “Client-side rendering is a ranking penalty.” (bản dịch) «Client-side kết xuất là một xếp hạng hình phạt.» Không trực tiếp CSR hình phạt tồn tại. Đó damage là gián tiếp — failed/delayed kết xuất, soft 404s, và duplicate clustering từ render timeouts reduce điều gì nhận được lập chỉ mục.
  • “Pre-rendering for bots is cloaking.” (bản dịch) «Pre-kết xuất cho bots là cloaking.» Không khi đó nội dung matches điều gì người dùng eventually see — chỉ đó khi/nơi of kết xuất differs, không đó nội dung.
  • “You need a special SPA sitemap generator.” (bản dịch) «Bạn cần một special SPA sitemap generator.» Không special format tồn tại; đó hoạt động là đang làm mỗi listed route resolve để real HTML.

FAQs

có thể Google chỉ mục single-trang application? Có, nếu mỗi route resolves để thực, unique HTML (qua SSR/prerendering) tại thực URL. Bare client-chỉ SPAs thường không.

Làm I cần SSR, hoặc là client-side kết xuất bao giờ okay? CSR có thể hoạt động cho nội dung đó không cần để xếp hạng, nhưng cho bất cứ điều gì bạn muốn được lập chỉ mục reliably, prerender hoặc SSR nó — không bet on renderer executing của bạn JS trong time.

là hash (#!) routing bad Đối với SEO? Có — fragment không bao giờ reaches máy chủ, so Google có thể’t reliably resolve những điều đó các URL. sử dụng History API.

Làm mỗi route cần của nó own thẻ canonical? Có, trong được kết xuất DOM — và làm sure không có gì nhiều hơn restrictive ( stray noindex hoặc sai canonical) ships trong thô shell.

là prerendering service cloaking? Không, provided nội dung phân phối để bots matches Điều gì người dùng see.

nên I sử dụng meta-framework thay vì building routing myself? cho new xây dựng, thường có — tiếp theo.js/Nuxt/Angular-SSR/SvelteKit cho bạn SSR/SSG và theo-route metadata cho free.

Vì sao làm my SPA trả về 200 Đối với các trang đó không exist? vì client-side router giữ gốc 200 status cho virtual navigations. khắc phục nó với JS chuyển hướng để thực lỗi status hoặc được kết xuất noindex.

Add an expert note

Pin an expert quote

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