Sitemap 怎么自动生成

Sitemap 的作用,不是让页面"一定被收录",而是告诉搜索引擎:这个网站有哪些重要 URL,哪些页面更新了,哪些页面值得重新抓取。

sitemaps.org 的协议说明也明确提到,Sitemap 可以为搜索引擎提供页面 URL 和相关元数据,但不保证页面一定被搜索引擎收录。

当你的站点只有十几个页面时,手写 sitemap.xml 还能接受。一旦你有博客、模板、工具页、集成页、城市页、商品页、文档页,Sitemap 就应该自动生成。

本文参考了几类官方资料:

Sitemap 应该包含哪些页面

Sitemap 不是全站 URL 垃圾桶。

应该放进去的是你希望搜索引擎发现、抓取、索引的页面。

适合放入:

复制代码
首页
核心产品页
博客文章
文档页
模板页
工具页
集成页
分类页
重要专题页
多语言页面

不适合放入:

复制代码
登录页
后台页面
支付回调 URL
搜索结果页
筛选参数页
重复内容页
草稿页
无索引页面
用户私有页面
临时预览页面

Google 的 Sitemap 文档也建议,只包含你希望出现在搜索结果中的 URL。

每个 URL 要有来源

自动生成 Sitemap 的第一步,是明确 URL 来源。

常见来源:

bash 复制代码
静态路由:/、/pricing、/about
博客数据库:/blog/[slug]
文档系统:/docs/[slug]
模板库:/templates/[slug]
工具页:/tools/[slug]
集成页:/integrations/[app-a]/[app-b]
多语言路由:/en/...、/zh/...

不要在代码里手写一大串 URL。

更稳的方式是:每类页面都有一个数据源,Sitemap 从这些数据源收集"已发布、可索引"的页面。

只收录可索引页面

自动生成时一定要过滤页面状态。

每个内容项至少要有这些字段:

lua 复制代码
slug
status
noindex
updated_at
locale
canonical_url

生成时过滤:

lua 复制代码
status 必须是 published
noindex 不能为 true
slug 必须有效
canonical_url 不能指向别的页面
页面不能是私有内容
页面不能是临时预览

这一步非常重要。否则你可能把草稿、测试页、重复页、私有页都提交给搜索引擎。

XML 字段怎么填

标准 Sitemap 里最核心的字段是 loc

sitemaps.org 协议要求每个 URL 条目包含 loc,其他字段如 lastmodchangefreqpriority 是可选的。

常用字段:

复制代码
loc:完整 URL
lastmod:页面最后修改时间
changefreq:更新频率提示
priority:相对优先级提示

早期最重要的是 loclastmod

changefreqpriority 不要瞎填。搜索引擎不一定严格使用这些提示,错误填写也不会带来神奇加成。

Next.js 怎么生成

如果你用 Next.js App Router,可以用 app/sitemap.ts

Next.js 官方文档说明,sitemap.(xml|js|ts) 是一个特殊文件约定,可以用于生成符合 Sitemap XML 格式的文件。

一个简化思路:

javascript 复制代码
import type { MetadataRoute } from 'next'

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const baseUrl = 'https://example.com'
  const posts = await getPublishedPosts()

  return [
    {
      url: baseUrl,
      lastModified: new Date(),
    },
    ...posts.map((post) => ({
      url: `${baseUrl}/blog/${post.slug}`,
      lastModified: post.updatedAt,
    })),
  ]
}

真实项目里,不要把 baseUrl 写死在多个地方。最好来自环境变量或统一配置。

大站要拆分 Sitemap

sitemaps.org 协议规定,单个 Sitemap 文件最多包含 50,000 个 URL,未压缩大小不能超过 50MB。

如果你的页面超过这个规模,就需要拆分:

bash 复制代码
/sitemap.xml
/sitemap-posts-1.xml
/sitemap-posts-2.xml
/sitemap-templates.xml
/sitemap-integrations.xml

再用 Sitemap index 统一引用这些子 Sitemap。

早期站点一般用不到拆分,但程序设计时最好留出扩展空间。

多语言页面要特别处理

如果你有中文、英文、日文等多语言页面,Sitemap 不能只放一种语言。

需要考虑:

复制代码
每种语言是否有独立 URL
canonical 是否指向自己
是否需要 hreflang
翻译是否已经发布
不同语言页面是否都可索引

不要把未完成翻译或机器翻译草稿直接放进 Sitemap。

多语言页面最常见的问题,是英文页和中文页互相 canonical 错误,或者 Sitemap 里出现大量空壳翻译页。

什么时候重新生成

Sitemap 不一定要每次请求都实时查数据库。

常见策略:

vbnet 复制代码
构建时生成:适合静态内容
定时生成:适合每天或每小时更新
按需重新验证:适合 Next.js ISR
后台任务生成:适合大量页面
缓存生成结果:适合高访问站点

如果内容更新不频繁,构建时生成就够了。

如果你有大量用户生成内容、模板页或自动生成页面,可以用后台任务定期生成,并把结果放到对象存储或缓存里。

robots.txt 要指向 Sitemap

提交 Sitemap 有几种方式:

arduino 复制代码
robots.txt 中声明 Sitemap
Google Search Console 手动提交
站点自动暴露 /sitemap.xml

robots.txt 里可以写:

arduino 复制代码
Sitemap: https://example.com/sitemap.xml

这样爬虫访问 robots.txt 时就能发现 Sitemap。

自动化检查

自动生成以后,还要检查。

建议检查:

arduino 复制代码
是否能访问 /sitemap.xml
Content-Type 是否正确
URL 是否都是绝对地址
是否包含草稿和 noindex 页面
lastmod 是否合理
URL 是否返回 200
是否包含重定向 URL
是否混入本地测试域名
是否超过 50,000 URL 或 50MB
Search Console 是否能读取

Sitemap 不是生成一次就完事。它是 SEO 基础设施,需要随着内容系统一起维护。

一个最小可用方案

独立开发者可以这样做:

bash 复制代码
1. 页面数据里加入 status、noindex、updated_at
2. 写一个统一的 getIndexableUrls()
3. 用 app/sitemap.ts 或构建脚本生成 Sitemap
4. 只输出 published 且可索引页面
5. URL 使用生产域名绝对地址
6. robots.txt 指向 /sitemap.xml
7. 提交到 Search Console
8. 每次发布后检查 Sitemap 是否可读

这套方案不复杂,但可以避免大多数 Sitemap 常见错误。

写在最后

Sitemap 的核心不是 XML 文件,而是"哪些页面值得被搜索引擎发现"的规则。

自动生成 Sitemap 时,真正重要的是数据源、可索引状态、更新时间、绝对 URL、多语言关系和持续检查。

只要这些规则清楚,Sitemap 就可以变成稳定的 SEO 基础设施,而不是每次上线前手改的文件。

下一篇,我们继续聊内容分发:RSS 有必要做吗

相关推荐
神奇小汤圆1 小时前
深入 Java 线程池:从源码原理、生产调优到故障排查全链路指南
后端
Conan在掘金2 小时前
ArkTS 进阶之道(30):@Track 精准观测边界——为啥 class 属性级观测只刷关联 UI 根因
后端
明月_清风2 小时前
🚀 OpenAI 数据代理架构全解析:从 600 PB 到自然语言的六层上下文工程
前端·后端·架构
明月_清风2 小时前
🚀 从 Foundry 到 AIP:Palantir 发生了什么变化?一篇文章全搞懂
前端·后端
Zane19942 小时前
闭包到底"闭"住了什么?一文讲透 LEGB 规则与循环里的闭包陷阱
后端·python
techdashen2 小时前
Go设计取舍之六: sync.Mutex正常模式与饥饿模式
开发语言·后端·golang
Zane19942 小时前
CAS 与原子类:Java 如何实现无锁编程
java·后端
颜进强2 小时前
前端看后端 13:什么是 Cookie 和 Session?
前端·后端
gitboyzcf2 小时前
mpegts.js解决Chrome无法播放7568×142分辨率报错 DOMException问题
前端·后端