sitemap.xml 找不到:3 个原因 + 修复路径

/sitemap.xml 或 /sitemap-index.xml 返回 404——通常是集成没启用或 `site` 没配。

你在 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/sitemapsite 拼接每个 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.xmlsitemap-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,
    }),
  ],
});

确认两点:

  • sitehttps:// 开头的绝对 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 测试

相关阅读

标签: #部署 / 托管 #排查 #排查 #Sitemap #SEO