你在 Search Console 提交 https://yourdomain.com/sitemap.xml,状态显示 “Couldn’t fetch” 或 “404”——这是部署 Astro / Next / Hugo 站点时几乎每个人都踩过的坑。Astro 的 @astrojs/sitemap 集成必须在 astro.config.mjs 里显式注册才会工作,并且严格依赖 site 字段;缺其中任何一个,build 都不会报错,但 dist/ 里就是没有 sitemap-index.xml。
本文按命中率列出 5 类原因,并给出能直接在 dist/ 验证的修复路径。
常见原因
按命中率从高到低:
1. 没在 astro.config 注册 @astrojs/sitemap
光 npm install @astrojs/sitemap 不够,必须在 config 里加进 integrations 数组:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://yourdomain.com',
integrations: [sitemap()],
});
少了 integrations: [sitemap()] 这一行,dist/sitemap-index.xml 就不会被生成。
如何判断:
grep -n "sitemap" astro.config.mjs
只看到 import 没看到调用 → 漏注册。
2. site 字段为空
@astrojs/sitemap 用 site 拼接每个 URL 的绝对地址。如果 site 没设,integration 会在构建时打 warning(很多人没看到)并直接跳过生成,dist/sitemap-index.xml 不会出现。
如何判断:跑 npm run build 看输出,如果有 [sitemap] \site` option is required`,就是这个。
3. 宿主 rewrite 把 /sitemap* 当作未匹配路径
跟 RSS 同病——Vercel / Netlify 的 SPA fallback /* /index.html 会吞掉 sitemap。Astro 静态部署多数没这个问题,但你如果手动配过 vercel.json rewrites,就要检查。
如何判断:
curl -I "https://yourdomain.com/sitemap.xml"
curl -I "https://yourdomain.com/sitemap-index.xml"
200 但 content-type: text/html → SPA fallback 接管。
4. URL 用错——应该是 sitemap-index.xml
@astrojs/sitemap 默认产出的是 sitemap-index.xml + 多个 sitemap-0.xml,不是 sitemap.xml。如果你只在 Search Console 提交了 /sitemap.xml,会拿到 404。
如何判断:
ls dist/sitemap*
如果只有 sitemap-index.xml 和 sitemap-0.xml,那就提交 sitemap-index.xml。
5. base 路径偏移
如果你的 Astro 配置了 base: '/blog',sitemap 会输出到 dist/blog/sitemap-index.xml,访问 /sitemap.xml(无 base)就是 404。
如何判断:
grep -n "base:" astro.config.mjs
find dist -name "sitemap*"
实际位置带 base 前缀就是这个原因。
最短修复路径
按收益从高到低,前 3 步通常解决 80% 的问题。
Step 1:把 @astrojs/sitemap 注册到 config
完整可用的最小配置:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://yourdomain.com', // 必须有,且是绝对 URL
integrations: [
sitemap({
filter: (page) => !page.includes('/admin/'),
changefreq: 'weekly',
priority: 0.7,
}),
],
});
确认两点:
site是https://开头的绝对 URL,不带末尾斜杠sitemap()出现在integrations里且被实际调用(注意有括号)
Step 2:本地 build 验证产物
rm -rf dist/
npm run build
ls dist/sitemap*
head -20 dist/sitemap-index.xml
期望看到:
dist/sitemap-0.xml
dist/sitemap-index.xml
sitemap-index.xml 内容应该指向 https://yourdomain.com/sitemap-0.xml。如果 site 配的不对,这里会暴露——比如指向 http://localhost:4321/sitemap-0.xml,部署上去 Google 拉不到。
Step 3:部署后用 curl 验证线上
curl -I "https://yourdomain.com/sitemap-index.xml"
curl -s "https://yourdomain.com/sitemap-index.xml" | head -10
通过标准:
- 状态 200
content-type: application/xml- 内容包含
<sitemapindex标签
200 但是 HTML → rewrite 拦截,去 vercel.json / netlify.toml 检查 SPA fallback。
Step 4:把正确的 URL 提交到 Search Console
到 Search Console → Sitemaps,提交:
https://yourdomain.com/sitemap-index.xml
注意是 sitemap-index.xml,不是 sitemap.xml(除非你自定义过 customPages + 重命名)。提交后状态应当在几分钟到几小时内变成 “Success”。
同时把 sitemap 写进 robots.txt:
Sitemap: https://yourdomain.com/sitemap-index.xml
让其他搜索引擎(Bing、Yandex)自动发现。
Step 5:CI 部署后冒烟测试
#!/usr/bin/env bash
set -e
URL="https://yourdomain.com/sitemap-index.xml"
status=$(curl -s -o /dev/null -w "%{http_code}" "$URL")
[[ "$status" == "200" ]] || { echo "Sitemap status: $status"; exit 1; }
curl -s "$URL" | grep -q "<sitemapindex" || { echo "Not a sitemap index"; exit 1; }
echo "Sitemap OK"
挂在部署成功 hook 上,任何 commit 不小心删了 sitemap() 调用都会立刻被发现。
预防建议
- 把 sitemap CI 检查放进
prebuild或部署后冒烟,保证dist/sitemap-index.xml始终存在 - 在 Search Console 提交后,每周看一次状态,第一时间发现 URL 数变化
robots.txt里写明Sitemap:行,让 Bing / Yandex 也能自动发现- 别把 sitemap 路径硬编码到模板里,直接信任
@astrojs/sitemap默认输出 - 改
site字段或base路径时连带 review sitemap 测试