Патэрн · 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
}
Праверка
Што праверыць:
-
Файл аддаецца. Адкрыйце
https://your-domain/sitemap.xml— павінен быць XML, а не HTML 404. Калі бачыце абалонку Next, упэўніцеся, што ёсцьapp/sitemap.ts(ці.js) з default-функцыяй. -
Search Console. У Google Search Console → Sitemaps дашліце
https://your-domain/sitemap.xml. «Couldn't fetch» або памылкі парсінгу азначаюць, што бот не атрымлівае сапраўдны XML. -
Супадзенне з canonical. Выберыце некалькі URL з файла, адкрыйце старонкі, знайдзіце
<link rel="canonical" ...>. Павінен супадаць з URL у sitemap (уключна з завершальным/, калі такая палітыка). -
Згоднасць з noindex. Старонкі з
robots: { index: false }або<meta name="robots" content="noindex">звычайна не павінны быць у спісе — іначай вы адпраўляеце супярэчлівыя сігналы.
Крыніцы
Іншыя патэрны
Матэрыялы блога
- SEO
Шматмоўнасць для B2B: чаму віджэт-перакладчык не роўны экспарту ў пошуку
Пераклад на старонцы і індэксуемыя моўныя версіі — розныя задачы. Разбіраем URL, мета, давер і лесвіцу сталасці для паставак і экспарту без зайвай магіі.
Чытаць артыкул - SEO
SEO-архітэктура: чаму сайт не прадае без структуры
Як правільная структура сайта ўплывае на продажы і пазіцыі ў пошуку. Чаму дызайн на другім плане, а семантыка на першым.
Чытаць артыкул
Трэба ўнясці пад ваш домен і стэк?
Кароткая форма: імя, тэлефон і сайт. Пасля адпраўкі — адказ з парадкам работ і арыенцірам па этапах; дэталі ўдакладняюцца пры кантакце.