Да асноўнага зместу

Патэрн · TypeScript

Дынамічны sitemap.xml у Next.js (app/sitemap.ts)

Адзін sitemap са статычнымі і кантэнтнымі URL; узгоднена з collectIndexableUrls і кананічнымі адрасамі.

Узровень: сярэдніАцэнка часу: ~40 хв

Генератар sitemap збірае стабільныя шляхі і slug з CMS/файлаў; lastmod — з дат кантэнту, калі даступна.

  • Кожны URL у sitemap павінен супадаць з canonical
  • не ўключайце noindex-старонкі
  • для вялікіх каталогаў — падзел або sitemap index

app/sitemap.ts у App Router вяртае масіў URL. За адзін праход збярыце статычныя маршруты і дынамічныя slug (блог, бібліятэка, кейсы).

Код

Ніжэй — логіка з app/sitemap.ts гэтага праекту (статычныя шляхі, кейсы, пасты, патэрны бібліятэкі):

import type { MetadataRoute } from 'next'
import { caseSlugOrder } from '@/data/cases'
import { SITE_STATIC_PATHS } from '@/data/site-static-paths'
import { getAllPosts, getPostModifiedDate } from '@/lib/blog'
import { getAllLibraryEntries, getLibraryModifiedDate } from '@/lib/library'
import { getStaticPagesLastModified } from '@/lib/site-static-lastmod'
import { getSiteUrl } from '@/lib/site'

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const site = getSiteUrl()
  const base = site.replace(/\/$/, '')
  const staticLastMod = getStaticPagesLastModified()
  const posts = await getAllPosts()
  const library = await getAllLibraryEntries()

  const entries: MetadataRoute.Sitemap = [
    ...SITE_STATIC_PATHS.map((path) => ({
      url: `${base}${path}`,
      lastModified: staticLastMod,
      changeFrequency: 'weekly' as const,
      priority: path === '/' ? 1 : 0.7,
    })),
    ...caseSlugOrder.map((slug) => ({
      url: `${base}/kejsy/${slug}/`,
      lastModified: staticLastMod,
      changeFrequency: 'monthly' as const,
      priority: 0.65,
    })),
    ...posts.map((p) => ({
      url: `${base}/blog/${p.slug}/`,
      lastModified: new Date(getPostModifiedDate(p)),
      changeFrequency: 'monthly' as const,
      priority: 0.6,
    })),
    ...library.map((e) => ({
      url: `${base}/biblioteka/${e.slug}/`,
      lastModified: new Date(getLibraryModifiedDate(e)),
      changeFrequency: 'monthly' as const,
      priority: 0.62,
    })),
  ]
  return entries
}

Праверка

Што праверыць:

  1. Файл аддаецца. Адкрыйце https://your-domain/sitemap.xml — павінен быць XML, а не HTML 404. Калі бачыце абалонку Next, упэўніцеся, што ёсць app/sitemap.ts (ці .js) з default-функцыяй.

  2. Search Console. У Google Search Console → Sitemaps дашліце https://your-domain/sitemap.xml. «Couldn't fetch» або памылкі парсінгу азначаюць, што бот не атрымлівае сапраўдны XML.

  3. Супадзенне з canonical. Выберыце некалькі URL з файла, адкрыйце старонкі, знайдзіце <link rel="canonical" ...>. Павінен супадаць з URL у sitemap (уключна з завершальным /, калі такая палітыка).

  4. Згоднасць з noindex. Старонкі з robots: { index: false } або <meta name="robots" content="noindex"> звычайна не павінны быць у спісе — іначай вы адпраўляеце супярэчлівыя сігналы.

Крыніцы

Трэба ўнясці пад ваш домен і стэк?

Кароткая форма: імя, тэлефон і сайт. Пасля адпраўкі — адказ з парадкам работ і арыенцірам па этапах; дэталі ўдакладняюцца пры кантакце.