Panduan Berikutnya.js SEO

cara membuat sebuah Berikutnya.js situs dapat di-crawl, dapat diindeks, dan rankable — dua routers, rendering modes (SSG/SSR/ISR/server Components), App Router Metadata API, sitemap.ts, robots.ts, berikutnya/image, berikutnya/tautan, dan mistakes itu diam-diam break ini.

Pertama kali diterbitkan: 26 Jun 2026 · Terakhir diperbarui: 3 Agu 2026 · Lanjutan

Berikutnya.js solves hardest JavaScript SEO masalah oleh default — jika Anda gunakan ini right. App Router's server Components dan SSG/ISR put konten di HTML so ada Tidak render-queue delay; native Metadata API resolves judul, canonicals, dan Open Graph pada server; sitemap.ts dan robots.ts adalah file conventions. kerangka kerja memberikan Anda infrastructure tetapi menulis none dari Anda tags untuk Anda. failures adalah predictable: missing metadataBase, Tidak priority pada LCP image, metadata exported dari sebuah Client Component (silently melakukan tidak ada apa pun), dan 404 views returning 200.

TL;DR — Berikutnya.js solves hardest JavaScript SEO masalah oleh default ketika Anda gunakan ini right. App Router defaults untuk server Components dan mendukung SSG/SSR/ISR — semua dari yang ship dirender HTML, so ada Tidak render-queue delay. Set metadata dengan native Metadata API (metadata / generateMetadata), dan remember metadataBase atau Anda canonicals dan OG images go relative. gunakan app/sitemap.ts dan app/robots.ts, pre-bangun dynamic routes dengan generateStaticParams, set priority pada LCP image, dan pertahankan tautan sebagai nyata next/link anchors. halaman Router adalah juga SEO-capable melalui next/head. failures adalah predictable — dan sebagian besar dari them tidak Berikutnya.js’s fault, mereka’re yours.

Di mana Berikutnya.js fits

Berikutnya.js adalah sebuah React kerangka kerja, so semuanya di JavaScript SEO applies. Apa membuat ini worth -nya own guide adalah itu Berikutnya.js ships pertama-class jawaban untuk sebagian besar JS-SEO masalah: server rendering, static generation, sebuah metadata sistem, dan sitemap/robots conventions. hard bagian tidak apakah Google dapat baca ini — Google memiliki dirender JavaScript untuk tahun — ini adalah choosing right rendering mode dan tidak leaving SEO basics unwired. ini adalah sebuah specialized case dari CMS headless SEO: CMS barely penting, frontend’s rendering decisions decide semuanya.

Satu framing untuk pertahankan straight: “ini adalah a Berikutnya.js site” (terjemahan) “ini adalah sebuah Berikutnya.js situs” tidak tell Anda bagaimana apa pun single URL adalah delivered. rendering mode, caching, dan server/Client Component boundaries adalah set per route (sometimes per segment) — sebuah project dapat mix sebuah static marketing halaman, sebuah SSR product halaman, dan sebuah Client Component dashboard. jangan extrapolate satu route’s perilaku untuk “itu seluruh app” (terjemahan) “ seluruh app”; test spesifik URL.

Dua routers, dua sets dari mechanics

Berikutnya.js memiliki dua routers, dan mereka tangani SEO differently:

  • halaman Router ( older model) — data fetching melalui getStaticProps / getServerSideProps; metadata melalui <Head> dari next/head (atau next-seo package); Tidak server Components.
  • App Router (v13+, saat ini dan recommended approach) — React server Components oleh default; native Metadata API (metadata export / generateMetadata); file conventions untuk app/sitemap.ts dan app/robots.ts; generateStaticParams untuk dynamic routes. Bukti untuk klaim ini The App Router uses Server Components and supports generateStaticParams plus metadata file conventions. Cakupan: Current Next.js App Router behavior; route rendering can become dynamic based on APIs used. Tingkat keyakinan: tinggi · Diverifikasi: Next.js: Server and Client Components Next.js: generateStaticParams

Keduanya dapat peringkat well. App Router memberikan Anda sebuah cleaner, integrated metadata sistem (Tidak next/head juggling) dan server Components out dari box, yang adalah mengapa I’d reach untuk ini pada sebuah baru bangun. tetapi “App Router atau Anda tidak dapat lakukan SEO” (terjemahan) “App Router atau Anda dapat’t melakukan SEO” adalah sebuah myth — plenty dari halaman Router situs peringkat fine.

rendering modes dan apa setiap berarti untuk SEO

«How Google handles JavaScript is a three-phase pipeline — crawl, then a deferred render wave, then index. “All pages with a 200 HTTP status code are sent to the rendering queue.” The whole game in Next.js is choosing a mode that puts your content in the HTML before that render wave, so there’s nothing to wait for. Bukti untuk klaim ini Google crawls, renders, and indexes JavaScript pages, and successful pages can enter the rendering queue. Cakupan: Google Search processing, not a promise that a URL will be indexed. Tingkat keyakinan: tinggi · Diverifikasi: Google: JavaScript SEO basics » (Terjemahan) (Ringkasan bahasa Indonesia untuk bagian dua puluh tujuh, bagian kecil satu: teks sumber dipertahankan agar dapat diperiksa dalam tinjauan penutur asli.)

  • Static situs Generation (SSG) — halaman pre-dirender di bangun time. HTML adalah immediately tersedia dengan Tidak render-queue risk. Best untuk konten itu tidak perubahan setiap minute. generateStaticParams() (App Router) / getStaticPaths() (halaman Router) decides yang dynamic routes mendapatkan pre-dibangun.
  • Incremental Static Regeneration (ISR) — static halaman itu revalidate setelah sebuah set interval (export const revalidate = 3600). crawler mendapatkan static HTML dengan rendah TTFB dan konten tetap fresh. sebuah strong default — dengan satu trap: setelah window expires berikutnya permintaan (possibly Googlebot) masih mendapatkan stale halaman; fresh versi menyajikan pada permintaan setelah itu. untuk genuinely volatile data (prices, stock), SSR adalah safer.
  • rendering sisi server (SSR) — HTML dirender per permintaan. crawler mendapatkan fully dirender HTML immediately; tradeoff adalah server latency, so watch TTFB dan LCP. export const dynamic = 'force-dynamic' atau menggunakan permintaan-time APIs (cookies, headers) opts sebuah route ke SSR.
  • React server Components (App Router default) — render pada server dan kirim HTML; Tidak JavaScript ships untuk component itself. konten adalah di awal respons dengan Tidak hydration kesenjangan. ini adalah best default untuk SEO. Interactivity lives di Client Components marked 'use client'.
  • rendering sisi klien (CSR) — dirender entirely di browser. Googlebot dapat indeks ini setelah render wave (median ~10 seconds, tetapi 90th percentile stretches untuk hours), dan lainnya crawler — Bingbot, AI bot, social preview bot — dapat mendapatkan sebuah empty halaman. di App Router, CSR adalah opt-di ('use client'); di halaman Router, hindari fetching utama konten di useEffect. jangan gunakan ini untuk konten Anda ingin diperingkatkan.

sebuah reminder I pertahankan coming back untuk: “Googlebot dapat render it” (terjemahan) “Googlebot dapat render ini” adalah tidak yang sama sebagai “Anda seharusnya membuat Googlebot render it.” (terjemahan) “Anda harus membuat Googlebot render ini.” rendering adalah expensive, deferred, dan tidak universal di seluruh crawler.

Metadata API (App Router)

Metadata API adalah server Component hanya — metadata resolves pada server sebelum halaman renders, so ini lands di awal HTML. Export metadata dari layout.js atau page.js:

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

atau, ketika tags bergantung pada fetched data, gunakan generateMetadata():

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

fields itu penting untuk SEO:

  • title — mendukung sebuah string, sebuah template ('%s | Brand'), sebuah default, dan sebuah absolute override. atur template setelah di root layout dan per-halaman judul inherit ini.
  • description, alternates.canonical ( correct cara untuk set sebuah canonical di App Router), openGraph (images harus resolve untuk absolute URLs), twitter (juga digunakan oleh LinkedIn dan Slack previews), dan robots (indeks/ikuti plus googleBot-spesifik directives like max-snippet, max-image-preview).
  • metadataBasediperlukan untuk canonical dan OG image URLs untuk resolve correctly. Forgetting ini adalah single sebagian besar umum Berikutnya.js metadata bug: relative URLs leak ke Anda canonical dan Open Graph tags, breaking social previews dan muddying canonical sinyal.

sebuah judul-template contoh:

// 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>

Dua gotchas. pertama, metadata adalah shallowly digabungkan dari layout untuk halaman — sebuah nested object like openGraph didefinisikan di sebuah child segment replaces parent’s entirely, so sebuah halaman-tingkat openGraph: { title: 'Home' } diam-diam drops apa pun openGraph.images set di layout. kedua — dan ini satu bites orang — metadata hanya berfungsi di server Components. Export ini dari sebuah 'use client' file dan ini silently melakukan tidak ada apa pun.

«Streaming metadata. For dynamically rendered pages, generateMetadata can stream the metadata after the initial HTML. Googlebot executes JavaScript and inspects the full DOM, so streamed metadata works for Google. But Next.js detects “HTML-limited bots” — Bingbot, Twitterbot, Slackbot, facebookexternalhit — and ships them blocking metadata in the <head> instead. Per the Next.js docs, “streaming metadata is disabled for bots and crawlers that expect metadata to be in the <head> tag.” This is automatic; no configuration needed. It’s a detail almost no competing guide covers, and it’s why streaming metadata isn’t a risk for the bots that can’t wait for it. Prerendered pages are a different case entirely — metadata there resolves at build time, so there’s no stream to worry about. This behavior is version-specific (current as of Next.js 16.2.10); re-check the generateMetadata docs when you upgrade. And because delivery paths differ by entry point, verify metadata two ways, not one: a direct/production request (curl -I or View Source) and a client-side navigation to the same route — the head can update differently between the two.

Bukti untuk klaim ini Prerendered Next.js pages do not use streaming metadata because metadata is resolved at build time in the documented path. Cakupan: route output, metadata and deployment Tingkat keyakinan: tinggi · Diverifikasi: Metadata and OG images

» (Terjemahan) (Ringkasan bahasa Indonesia untuk bagian empat puluh, bagian kecil satu: teks sumber dipertahankan agar dapat diperiksa dalam tinjauan penutur asli.)

Metadata dengan berikutnya/head (halaman Router)

pada halaman Router, metadata lives di <Head> dari 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 */}
    </>
  )
}

Set judul dan deskripsi per halaman (tidak hanya di _app.js), dan put sebuah canonical pada setiap halaman including paginated variants. next-seo package standardizes ini dengan sebuah <NextSeo> component dan structured-data helpers. Migrating untuk App Router mostly berarti trading next/head dan next-seo untuk native metadata export.

melakukan Anda perlu next-seo package? ini adalah sebuah ketiga-party plugin (tidak bagian dari Berikutnya.js itself) — actively maintained, di v7.2,0 sebagai dari ini writing, tidak archived. -nya own docs adalah jelas tentang di mana ini fits: untuk standard meta tags pada App Router, package’s README recommends menggunakan Berikutnya.js’s dibangun-di generateMetadata/metadata export alih-alih <NextSeo>; pada halaman Router, <NextSeo> adalah masih sebuah reasonable convenience layer di atas next/head. satu App Router gunakan case package masih covers adalah -nya JSON-LD helper components (ArticleJsonLd, FAQPageJsonLd, dan seterusnya. dengan useAppDir), yang beberapa tim prefer di atas hand-rolling <script type="application/ld+json">. Bottom line: pada sebuah baru App Router bangun, reach untuk native Metadata API pertama — package adalah opsional, tidak sebuah requirement, dan -nya own maintainers say so.

Sitemaps

di App Router, app/sitemap.ts adalah sebuah file convention itu 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 },
  ]
}

untuk besar situs, generateSitemaps() shards ke multiple files (Google’s limit adalah 50 000 URLs per sitemap), setiap disajikan di /.../sitemap/[id].xml. sitemap output juga mendukung image sitemaps, video sitemaps, dan localized alternates.languages. pada halaman Router, gunakan next-sitemap atau generate pages/sitemap.xml.js dengan getServerSideProps.

robots.txt

app/robots.ts generates Anda robots file programmatically:

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

Per-pengguna-agent aturan dan multiple sitemaps adalah didukung. halaman Router menggunakan sebuah static public/robots.txt. aturan Anda cannot mendapatkan wrong pada either router: tidak pernah disallow Anda JavaScript atau CSS — Google tidak akan render dari blocked files, dan pada sebuah JS kerangka kerja itu dapat blank out halaman entirely.

berikutnya/image dan Core Web Vitals

next/image adalah satu dari strongest alasan untuk gunakan kerangka kerja untuk SEO. ini lazy-memuat di bawah—fold images, memerlukan width/height (atau fill) so ini reserves space dan mencegah layout shift / CLS, menyajikan WebP/AVIF secara otomatis, dan emits sebuah proper srcset dari sizes prop. single sebagian besar penting CWV optimization adalah priority prop pada Anda hero / di atas—fold image, yang preloads ini untuk sebuah lebih cepat LCP:

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

Forgetting priority pada LCP image adalah paling umum Berikutnya.js CWV mistake — dan CWV masalah adalah widespread pada nyata Berikutnya.js situs (see Stats tab untuk Salt Agency data). alt adalah diperlukan: empty untuk decorative images, descriptive untuk konten images.

berikutnya/tautan dan internal linking

next/link renders standard <a href> anchors di HTML, so Google mengikuti them biasanya, dan ini menambahkan client-side navigation plus background prefetching dari di-viewport tautan di production. SEO aturan adalah sederhana: gunakan next/link untuk tautan internal, dan tidak pernah substitute sebuah onClick handler atau JavaScript navigation itu tidak produce sebuah nyata anchor — itu tautan tidak dapat di-crawl. gunakan prefetch={false} pada rendah-nilai tautan untuk save bandwidth jika Anda perlu.

Dynamic routes dan generateStaticParams

generateStaticParams() tells Berikutnya.js yang dynamic routes untuk pre-render di bangun time:

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

halaman dibangun ini cara adalah fully static HTML — best untuk SEO. Tanpa ini, dynamic routes adalah dirender pada-demand (SSR) oleh default, yang adalah fine tetapi reintroduces server latency. Combine ini dengan revalidate (ISR) untuk konten itu memperbarui regularly. pastikan semua penting dynamic URLs adalah di generateStaticParams so tidak ada apa pun menunggu pada render queue.

data terstruktur (JSON-LD)

Metadata API memiliki Tidak structured-data field — Anda inject JSON-LD sebagai sebuah <script> di sebuah server Component, yang mempertahankan ini di server-dirender HTML di zero client-bundle cost:

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

artikel/BlogPosting, BreadcrumbList, Product, dan FAQPage adalah biasa jenis. Validate dengan Rich hasil Test setelah apa pun rendering perubahan.

umum Berikutnya.js SEO mistakes

Drawn dari nyata audits dan patterns di atas:

  1. Missing atau relative canonicals — sering dari sebuah forgotten metadataBase, yang juga breaks OG image URLs.
  2. Tidak priority pada LCP image — biggest CWV miss.
  3. 404 views returning 200 — gunakan dibangun-di notFound() untuk mengembalikan nyata status; soft 404s adalah rampant pada Berikutnya.js situs.
  4. metadata exported dari sebuah Client Component — silently melakukan tidak ada apa pun; ini adalah server Component hanya.
  5. CSR untuk utama konten — fetching critical konten di useEffect berarti non-Google crawler mendapatkan empty halaman.
  6. Hash (#) routing alih-alih History API — itu views tidak secara terpisah dapat di-crawl.
  7. Tidak exporting generateStaticParams — dynamic routes render pada-demand alih-alih menjadi pre-dibangun.
  8. openGraph overwritten oleh layout inheritance — child segments replace, tidak gabungkan.
  9. Blocking JS/CSS di robots.txt atau melalui sebuah konten Security Policy itu berhenti Googlebot’s headless Chrome dari memuat scripts — test dengan pemeriksaan URL.

Deployment notes

Berikutnya.js adalah dibangun oleh Vercel; hosting di sana memberikan tight integration (edge CDN untuk static dan ISR halaman, baik TTFB) tetapi tidak diperlukan. Define permanent redirects di redirects() di next.config.js (mengembalikan 308, atau 301 dengan permanent: true) untuk reliable signaling untuk crawler, set security dan caching headers melalui headers(), dan gunakan X-Robots-Tag respons headers untuk path-based noindex aturan ketika per-halaman robots metadata adalah awkward.

Apa untuk periksa di mana. Cache state, kode status, redirects, dan streamed metadata jangan semua tampilkan up di yang sama test — sebuah route dapat look fine di satu periksa dan masih menjadi rusak di lainnya:

periksaDi mana untuk lookMengapa ini dapat differ dari apa Anda see dirender
Cache/revalidation agerespons headers pada sebuah direct permintaan (curl -I)ISR dapat sajikan stale halaman pada permintaan right setelah window expires
Direct HTTP statuscurl -I pada production URL, tidak dirender UIsebuah “tidak ditemukan” (terjemahan) “tidak ditemukan” view tanpa notFound() masih mengembalikan 200
Redirect perilakusebenarnya context itu fires ini — redirect() di sebuah server tindakan, sebuah Route Handler, vs. sebuah client onClickkode status dan respons path differ oleh invocation context, tidak hanya destination
Streamed metadataDirect permintaan dan client-side navigation untuk yang sama routeOrdinary clients dapat mendapatkan streamed metadata; HTML-limited bot mendapatkan blocking metadata; dua paths tidak identical
Client-side transitionsNavigate di-app, lalu re-periksa <head>sebuah route itu’s correct pada pertama muat dapat drift setelah sebuah client transition

None dari ini adalah guaranteed oleh kerangka kerja — Berikutnya.js memberikan Anda mechanisms (redirects(), notFound(), revalidation, streaming), tetapi cache keys, invalidation, preview state, dan deployment configuration adalah masih Anda responsibility untuk mendapatkan right dan untuk test di production, tidak hanya locally.

«One last note on dynamic rendering — serving prerendered HTML to bots and JavaScript to users. Google has deprecated it as a recommendation: “dynamic rendering was a workaround and not a long-term solution.” You don’t need it on Next.js anyway — SSR, SSG, ISR, and Server Components all put content in the HTML natively. Mention it so you recognize it in an audit; don’t build on it. » (Terjemahan) (Ringkasan bahasa Indonesia untuk bagian tujuh puluh enam, bagian kecil satu: teks sumber dipertahankan agar dapat diperiksa dalam tinjauan penutur asli.)

happy path: App Router + server Components + ISR + Metadata API (dengan metadataBase) + next/image dengan priority. Mendapatkan itu right dan sebagian besar dari Berikutnya.js SEO adalah handled.

Tambahkan catatan pakar

Sematkan kutipan pakar

Orang baru? Buat profilnya yang belum diklaim di /admin/experts/ → Sematkan kutipan pakar terlebih dahulu.