Tiếp theo.js SEO

Cách làm một Tiếp theo.js site crawlable, indexable, và rankable — đó hai routers, kết xuất modes (SSG/SSR/ISR/Máy chủ Components), đó App Router Metadata API, sitemap.ts, robots.ts, tiếp theo/image, tiếp theo/link, và đó mistakes đó âm thầm break điều này.

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ữ

Tiếp theo.js solves đó hardest JavaScript SEO các vấn đề theo mặc định — nếu bạn dùng điều này right. Đó App Router Máy chủ Components và SSG/ISR put nội dung trong đó HTML so có không render-queue delay; đó native Metadata API resolves các tiêu đề, canonicals, và Open Graph on đó máy chủ; sitemap.ts và robots.ts là file conventions. Đó framework cho bạn đó infrastructure nhưng ghi none of của bạn tags cho bạn. Đó failures là dễ dự đoán: bị thiếu metadataBase, không priority on đó LCP image, metadata exported từ một Client Component (silently làm không có gì), và 404 views returning 200.

Tóm tắt — tiếp theo.js solves hardest JavaScript SEO các vấn đề theo mặc định Khi bạn sử dụng nó right. App Router defaults để máy chủ Components và hỗ trợ SSG/SSR/ISR — tất cả mà ship được kết xuất HTML, so có không render-queue delay. đặt metadata với native Metadata API (metadata / generateMetadata), và remember metadataBase hoặc của bạn canonicals và OG images go relative. sử dụng app/sitemap.tsapp/robots.ts, pre-xây dựng dynamic routes với generateStaticParams, đặt priority on LCP image, và giữ links as thực next/link anchors. các trang Router là cũng SEO-capable qua next/head. failures là dễ dự đoán — và phần lớn của them không phải tiếp theo.js fault, họ’re yours.

nơi tiếp theo.js fits

tiếp theo.js là React framework, so mọi thứ trong JavaScript SEO áp dụng. Điều gì làm nó worth của nó own hướng dẫn là đó tiếp theo.js ships đầu tiên-class các câu trả lời để phần lớn JS-SEO các vấn đề: máy chủ kết xuất, static generation, metadata hệ thống, và sitemap/robots conventions. hard part không phải liệu Google có thể đọc nó — Google có được kết xuất JavaScript cho năm — nó chọn right kết xuất chế độ và không leaving SEO basics unwired. Đây là specialized case của headless CMS SEO: CMS barely matters, frontend kết xuất decisions quyết định mọi thứ.

Một cách diễn đạt để giữ straight: “this is a Next.js site” (bản dịch) «này là một Tiếp theo.js site» không tell bạn cách bất kỳ single URL là delivered. Kết xuất chế độ, bộ nhớ đệm, và Máy chủ/Client Component boundaries là set theo route (sometimes theo segment) — một project có thể mix một static marketing trang, an SSR sản phẩm trang, và một Client Component dashboard. không extrapolate một route behavior để “the whole app” (bản dịch) «đó toàn bộ app»; kiểm thử đó cụ thể URL.

Hai routers, hai sets của mechanics

tiếp theo.js có hai routers, và họ xử lý SEO differently:

  • các trang Router ( older model) — dữ liệu fetching qua getStaticProps / getServerSideProps; metadata qua <Head> từ next/head (hoặc next-seo package); không máy chủ Components.
  • App Router (v13+, hiện tại và được khuyến nghị approach) — React máy chủ Components theo mặc định; native Metadata API (metadata export / generateMetadata); file conventions cho app/sitemap.tsapp/robots.ts; generateStaticParams cho dynamic routes. Evidence for this claim The App Router uses Server Components and supports generateStaticParams plus metadata file conventions. Scope: Current Next.js App Router behavior; route rendering can become dynamic based on APIs used. Confidence: high · Verified: Next.js: Server and Client Components Next.js: generateStaticParams

Cả hai có thể xếp hạng well. Đó App Router cho bạn một cleaner, integrated metadata hệ thống (không next/head juggling) và Máy chủ Components out of đó box, mà là vì sao I’d reach cho điều này on một new xây dựng. Nhưng “App Router or you can’t do SEO” (bản dịch) «App Router hoặc bạn không thể làm SEO» là một myth — plenty of Các trang Router các trang xếp hạng fine.

Kết xuất modes và Điều gì mỗi có nghĩ là Đối với SEO

Cách Google xử lý JavaScript là một three-phase pipeline — crawl, thì một deferred render wave, thì chỉ mục. “All pages with a 200 HTTP status code are sent to the rendering queue.” (bản dịch) «All các trang với một 200 HTTP mã trạng thái là đã gửi để đó kết xuất queue.» Đó toàn bộ game trong Tiếp theo.js là chọn một chế độ đó diễn đạt nội dung của bạn trong đó HTML trước đó render wave, so có không có gì để chờ cho. Evidence for this claim Google crawls, renders, and indexes JavaScript pages, and successful pages can enter the rendering queue. Scope: Google Search processing, not a promise that a URL will be indexed. Confidence: high · Verified: Google: JavaScript SEO basics

  • Static trang web Generation (SSG) — các trang pre-được kết xuất tại xây dựng time. HTML là immediately khả dụng với không render-queue risk. Best cho nội dung đó không thay đổi mỗi minute. generateStaticParams() (App Router) / getStaticPaths() (các trang Router) decides mà dynamic routes nhận pre-được xây dựng.
  • Incremental Static Regeneration (ISR) — static các trang đó revalidate sau khi đặt interval (export const revalidate = 3600). Các crawler nhận static HTML với thấp TTFB và nội dung vẫn giữ fresh. mạnh default — với một trap: sau khi window expires tiếp theo yêu cầu (possibly Googlebot) vẫn nhận stale trang; fresh version phục vụ on yêu cầu sau khi đó. cho genuinely volatile dữ liệu (prices, stock), SSR là safer.
  • máy chủ-Side Kết xuất (SSR) — HTML được kết xuất theo yêu cầu. Các crawler nhận fully được kết xuất HTML immediately; tradeoff là máy chủ latency, so watch TTFB và LCP. export const dynamic = 'force-dynamic' hoặc sử dụng yêu cầu-time APIs (cookies, các header) opts route vào SSR.
  • React máy chủ Components (App Router default) — render on máy chủ và gửi HTML; không JavaScript ships cho component itself. nội dung là trong ban đầu phản hồi với không hydration khoảng trống. Đây là best default Đối với SEO. Interactivity lives trong Client Components marked 'use client'.
  • Client-Side Kết xuất (CSR) — được kết xuất hoàn toàn trong trình duyệt. Googlebot có thể chỉ mục nó sau khi render wave (median ~10 seconds, nhưng 90th percentile stretches để hours), và khác các crawler — Bingbot, AI bots, social preview bots — có thể nhận rỗng trang. Trong App Router, CSR là opt-trong ('use client'); trong các trang Router, tránh fetching chính nội dung trong useEffect. không sử dụng nó cho nội dung bạn muốn được xếp hạng.

MỘT reminder I giữ coming lại để: “Googlebot can render it” (bản dịch) «Googlebot có thể render điều này» không phải đó giống nhau as “you should make Googlebot render it.” (bản dịch) «bạn nên làm Googlebot render điều này.» Kết xuất là expensive, deferred, và không universal trên các crawler.

Metadata API (App Router)

Metadata API là máy chủ Component chỉ — metadata resolves on máy chủ trước khi trang renders, so nó lands trong ban đầu HTML. Export metadata từ layout.js hoặc page.js:

export const metadata: Metadata = {
  title: 'My Page',
  description: 'Page description',
}

hoặc, Khi tags phụ thuộc on fetched dữ liệu, sử dụng generateMetadata():

export async function generateMetadata({ params }) {
  const post = await getPost(params.slug)
  return { title: post.title, description: post.description }
}

các trường đó quan trọng Đối với SEO:

  • title — hỗ trợ string, template ('%s | Brand'), default, và absolute override. đặt template sau khi trong root layout và theo-trang các tiêu đề inherit nó.
  • description, alternates.canonical ( đúng way để đặt canonical trong App Router), openGraph (images phải resolve để absolute các URL), twitter (cũng được sử dụng by LinkedIn và Slack previews), và robots (chỉ mục/follow plus Googlebot-cụ thể directives như max-snippet, max-image-preview).
  • metadataBasebắt buộc cho canonical và OG image các URL để resolve correctly. Forgetting nó là single phần lớn phổ biến tiếp theo.js metadata bug: relative các URL leak vào của bạn canonical và Open Graph tags, breaking social previews và muddying canonical các tín hiệu.

tiêu đề-template ví dụ:

// app/layout.tsx
export const metadata: Metadata = {
  metadataBase: new URL('https://example.com'),
  title: { template: '%s | Brand Name', default: 'Brand Name' },
}
// app/blog/page.tsx
export const metadata: Metadata = { title: 'My Blog Post' }
// Output: <title>My Blog Post | Brand Name</title>

Hai gotchas. đầu tiên, metadata là shallowly đã hợp nhất từ layout để trang — nested object như openGraph được định nghĩa trong child segment replaces parent hoàn toàn, so trang-cấp độ openGraph: { title: 'Home' } âm thầm drops bất kỳ openGraph.images đặt trong layout. thứ hai — và điều này một bites mọi người — metadata chỉ hoạt động trong máy chủ Components. Export nó từ 'use client' file và nó silently làm không có gì.

Streaming metadata. Cho dynamically được kết xuất các trang, generateMetadata có thể stream đó metadata sau đó ban đầu HTML. Googlebot executes JavaScript và inspects đó đầy đủ DOM, so streamed metadata hoạt động cho Google. Nhưng Tiếp theo.js detects “HTML-limited bots” (bản dịch) «HTML-limited bots» — Bingbot, Twitterbot, Slackbot, facebookexternalhit — và ships them blocking metadata trong đó <head> thay vì. Theo đó Tiếp theo.js tài liệu, “streaming metadata is disabled for bots and crawlers that expect metadata to be in the <head> tag.” (bản dịch) «streaming metadata là disabled cho bots và các crawler đó expect metadata để là trong đó thẻ head tag.» Này là tự động; không configuration needed. đây là một detail gần như không competing hướng dẫn covers, và đây là vì sao streaming metadata không một risk cho đó bots đó không thể chờ cho điều này. Prerendered các trang là một khác nhau case hoàn toàn — metadata ở đó resolves tại xây dựng time, so có không stream để worry về. Này behavior là version-cụ thể (hiện tại as of Tiếp theo.js 16.2.10); re-kiểm tra đó generateMetadata tài liệu khi bạn upgrade. Và vì phân phối paths differ by entry point, verify metadata hai ways, không một: một trực tiếp/production yêu cầu (curl -I hoặc View Nguồn) một client-side navigation để đó giống nhau route — đó head có thể cập nhật differently giữa đó hai.

Evidence for this claim Prerendered Next.js pages do not use streaming metadata because metadata is resolved at build time in the documented path. Scope: route output, metadata and deployment Confidence: high · Verified: Metadata and OG images

Metadata với tiếp theo/head (các trang Router)

On các trang Router, metadata lives trong <Head> từ next/head:

import Head from 'next/head'

export default function Page() {
  return (
    <>
      <Head>
        <title>My Page | Brand</title>
        <meta name="description" content="Description" />
        <link rel="canonical" href="https://example.com/my-page" />
      </Head>
      {/* page content */}
    </>
  )
}

đặt tiêu đề và mô tả theo trang (không chỉ trong _app.js), và put canonical on mỗi trang including paginated variants. next-seo package standardizes điều này với <NextSeo> component và structured-dữ liệu helpers. Migrating để App Router mostly có nghĩ là trading next/headnext-seo cho native metadata export.

Làm bạn cần next-seo package? nó thứ ba-party plugin (không part của tiếp theo.js itself) — actively maintained, tại v7.2,0 as của điều này writing, không archived. Của nó own tài liệu là rõ ràng về nơi nó fits: cho tiêu chuẩn meta tags on App Router, package README khuyến nghị sử dụng tiếp theo.js được xây dựng-trong generateMetadata/metadata export thay vì <NextSeo>; on các trang Router, <NextSeo> là vẫn reasonable convenience layer over next/head. một App Router sử dụng case package vẫn covers là của nó JSON-LD helper components (ArticleJsonLd, FAQPageJsonLd, etc. với useAppDir), mà some nhóm ưu tiên over hand-rolling <script type="application/ld+json">. Bottom line: on new App Router xây dựng, reach cho native Metadata API đầu tiên — package là tùy chọn, không requirement, và của nó own maintainers chẳng hạn so.

Sitemaps

Trong App Router, app/sitemap.ts là file convention đó outputs /sitemap.xml:

import type { MetadataRoute } from 'next'

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    { url: 'https://acme.com', lastModified: new Date(), priority: 1 },
    { url: 'https://acme.com/blog', lastModified: new Date(), priority: 0.8 },
  ]
}

cho lớn các trang, generateSitemaps() shards vào multiple files (Google limit là 50 000 các URL theo sitemap), mỗi phân phối tại /.../sitemap/[id].xml. sitemap output cũng hỗ trợ image sitemaps, video sitemaps, và localized alternates.languages. On các trang Router, sử dụng next-sitemap hoặc generate pages/sitemap.xml.js với getServerSideProps.

robots.txt

app/robots.ts generates của bạn robots file programmatically:

export default function robots(): MetadataRoute.Robots {
  return {
    rules: [{ userAgent: '*', allow: '/', disallow: '/private/' }],
    sitemap: 'https://acme.com/sitemap.xml',
  }
}

Theo-người dùng-agent rules và multiple sitemaps là supported. các trang Router dùng static public/robots.txt. rule bạn không thể nhận sai on either router: không bao giờ disallow của bạn JavaScript hoặc CSS — Google sẽ không render từ blocked files, và on JS framework đó có thể blank out trang hoàn toàn.

tiếp theo/image và Core Web Vitals

next/image là một của strongest reasons để sử dụng framework Đối với SEO. nó lazy-loads dưới—fold images, requires width/height (hoặc fill) so nó reserves space và ngăn layout shift / CLS, phục vụ WebP/AVIF tự động, và emits proper srcset từ sizes prop. single phần lớn quan trọng CWV optimization là priority prop on của bạn hero / trên—fold image, mà preloads nó cho nhanh hơn LCP:

<Image src="/hero.jpg" width={1200} height={630} priority alt="Hero" />

Forgetting priority on LCP image là phần lớn phổ biến tiếp theo.js CWV mistake — và CWV các vấn đề là widespread on thực tiếp theo.js các trang (see Số liệu tab cho Salt Agency dữ liệu). alt là bắt buộc: rỗng cho decorative images, descriptive cho nội dung images.

next/link renders tiêu chuẩn <a href> anchors trong HTML, so Google follows them thông thường, và nó adds client-side navigation plus background prefetching của trong-viewport links trong production. SEO rule là đơn giản: sử dụng next/link cho liên kết nội bộ, và không bao giờ substitute onClick handler hoặc JavaScript navigation đó không produce thực anchor — những điều đó links không phải crawlable. sử dụng prefetch={false} on thấp-giá trị links để save bandwidth nếu bạn cần.

Dynamic routes và generateStaticParams

generateStaticParams() tells tiếp theo.js mà dynamic routes để pre-render tại xây dựng time:

// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await getPosts()
  return posts.map((post) => ({ slug: post.slug }))
}

các trang được xây dựng điều này way là fully static HTML — best Đối với SEO. không có nó, dynamic routes là được kết xuất on-demand (SSR) theo mặc định, mà là fine nhưng reintroduces máy chủ latency. Combine nó với revalidate (ISR) cho nội dung đó cập nhật regularly. hãy đảm bảo all quan trọng dynamic các URL là trong generateStaticParams so không có gì chờ on render queue.

Dữ liệu có cấu trúc (JSON-LD)

Metadata API có không structured-dữ liệu trường — bạn inject JSON-LD as <script> trong máy chủ Component, mà giữ nó trong máy chủ-được kết xuất HTML tại zero client-bundle cost:

const jsonLd = { '@context': 'https://schema.org', '@type': 'Article', /* … */ }
return <script type="application/ld+json"
  dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />

Bài viết/BlogPosting, BreadcrumbList, Sản phẩm, và FAQPage là thông thường types. Validate với Rich Kết quả Kiểm thử sau khi bất kỳ kết xuất thay đổi.

phổ biến tiếp theo.js SEO mistakes

Drawn từ thực audits và patterns trên:

  1. Bị thiếu hoặc relative canonicals — thường từ forgotten metadataBase, mà cũng breaks OG image các URL.
  2. Không priority on LCP image — biggest CWV miss.
  3. 404 views returning 200 — sử dụng được xây dựng-trong notFound() để trả về thực status; soft 404s là rampant on tiếp theo.js các trang.
  4. metadata exported từ Client Component — silently làm không có gì; nó máy chủ Component chỉ.
  5. CSR cho chính nội dung — fetching cốt yếu nội dung trong useEffect có nghĩ là non-Google các crawler nhận rỗng các trang.
  6. Hash (#) routing thay vì History API — những điều đó views không phải riêng crawlable.
  7. không exporting generateStaticParams — dynamic routes render on-demand thay vì là pre-được xây dựng.
  8. openGraph overwritten by layout inheritance — child segments replace, không hợp nhất.
  9. Blocking JS/CSS trong robots.txt hoặc qua nội dung Security Policy đó dừng Googlebot’s headless Chrome từ loading scripts — kiểm thử với URL Inspection.

Deployment notes

tiếp theo.js là được xây dựng by Vercel; hosting ở đó cho tight integration (edge CDN cho static và ISR các trang, good TTFB) nhưng không phải bắt buộc. Define vĩnh viễn các chuyển hướng trong redirects() trong next.config.js (trả về 308, hoặc 301 với permanent: true) cho reliable signaling để các crawler, đặt security và bộ nhớ đệm các header qua headers(), và sử dụng X-Robots-Tag phản hồi các header cho path-based noindex rules Khi theo-trang robots metadata là awkward.

Điều gì để kiểm tra nơi. bộ nhớ đệm state, các mã trạng thái, các chuyển hướng, và streamed metadata không all hiển thị lên trong giống nhau kiểm thử — route có thể look fine trong một kiểm tra và vẫn là hỏng trong một:

kiểm tranơi để lookVì sao nó có thể differ từ Điều gì bạn see được kết xuất
bộ nhớ đệm/revalidation agephản hồi các header on trực tiếp yêu cầu (curl -I)ISR có thể phục vụ stale trang on yêu cầu right sau khi window expires
Trực tiếp HTTP statuscurl -I on production URL, không được kết xuất UI”không tìm thấy” view không có notFound() vẫn trả về 200
chuyển hướng behaviorthực tế context đó fires nó — redirect() trong máy chủ Hành động, Route Handler, so với. client onClickmã trạng thái và phản hồi path differ by invocation context, không chỉ đích
Streamed metadataTrực tiếp yêu cầu client-side navigation để giống nhau routeOrdinary clients có thể nhận streamed metadata; HTML-limited bots nhận blocking metadata; hai paths không phải giống hệt
Client-side transitionsNavigate trong-app, sau đó re-kiểm tra <head>route đó đúng on đầu tiên load có thể drift sau khi client transition

None của Đây là guaranteed by framework — tiếp theo.js cho bạn mechanisms (redirects(), notFound(), revalidation, streaming), nhưng bộ nhớ đệm keys, invalidation, preview state, và deployment configuration là vẫn của bạn responsibility để nhận right và để kiểm thử trong production, không chỉ locally.

Một cuối cùng note on dynamic kết xuất — serving prerendered HTML để bots và JavaScript để người dùng. Google có deprecated điều này as một khuyến nghị: “dynamic rendering was a workaround and not a long-term 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.» Bạn không cần điều này on Tiếp theo.js anyway — SSR, SSG, ISR, và Máy chủ Components all put nội dung trong đó HTML natively. Mention điều này so bạn recognize điều này trong an audit; không xây dựng on điều này.

happy path: App Router + máy chủ Components + ISR + Metadata API (với metadataBase) + next/image với priority. Nhận những điều đó right và phần lớn của tiếp theo.js SEO là handled.

Add an expert note

Pin an expert quote

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