Skip to content

Sitemap 生成

生成 sitemap.xml 帮助搜索引擎更好地索引你的站点。

VitePress 内置支持

VitePress 内置 sitemap 生成功能:

ts
// .vitepress/config.mts
export default defineConfig({
  sitemap: {
    hostname: 'https://your-domain.com',
    lastmodDateOnly: false
  }
})

构建后会自动生成 sitemap.xml

完整配置

ts
export default defineConfig({
  sitemap: {
    hostname: 'https://your-domain.com',
    
    // 可选:自定义 URL
    transformItems(items) {
      return items.map(item => {
        // 设置优先级
        if (item.url === '/') {
          item.priority = 1.0
        } else if (item.url.includes('/guide/')) {
          item.priority = 0.9
        } else {
          item.priority = 0.7
        }
        
        // 设置更新频率
        if (item.url === '/') {
          item.changefreq = 'daily'
        } else {
          item.changefreq = 'weekly'
        }
        
        return item
      })
    }
  }
})

手动生成脚本

如果需要更多控制,可以手动生成:

ts
// scripts/generate-sitemap.ts
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'

const SITE_URL = 'https://your-domain.com'

interface SitemapUrl {
  loc: string
  lastmod?: string
  changefreq?: string
  priority?: number
}

const urls: SitemapUrl[] = []

function walk(dir: string) {
  const entries = fs.readdirSync(dir, { withFileTypes: true })
  
  for (const entry of entries) {
    const fullPath = path.join(dir, entry.name)
    
    if (entry.isDirectory() && !entry.name.startsWith('.')) {
      walk(fullPath)
    } else if (entry.name.endsWith('.md')) {
      const content = fs.readFileSync(fullPath, 'utf-8')
      const { data } = matter(content)
      
      const relativePath = fullPath
        .replace('docs/', '')
        .replace('.md', '')
        .replace(/index$/, '')
      
      urls.push({
        loc: `${SITE_URL}/${relativePath}`,
        lastmod: data.updated || data.date,
        changefreq: getChangeFreq(relativePath),
        priority: getPriority(relativePath)
      })
    }
  }
}

function getChangeFreq(path: string): string {
  if (path === '' || path === 'index') return 'daily'
  if (path.includes('/guide/')) return 'weekly'
  return 'monthly'
}

function getPriority(path: string): number {
  if (path === '' || path === 'index') return 1.0
  if (path.includes('/guide/')) return 0.9
  if (path.includes('/reference/')) return 0.8
  return 0.7
}

walk('docs')

// 生成 XML
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls.map(url => `  <url>
    <loc>${url.loc}</loc>
    ${url.lastmod ? `<lastmod>${url.lastmod}</lastmod>` : ''}
    ${url.changefreq ? `<changefreq>${url.changefreq}</changefreq>` : ''}
    ${url.priority ? `<priority>${url.priority}</priority>` : ''}
  </url>`).join('\n')}
</urlset>`

fs.writeFileSync('docs/public/sitemap.xml', sitemap)
console.log(`✅ Sitemap 已生成: ${urls.length} 个 URL`)

多语言 Sitemap

ts
interface AlternateLink {
  hreflang: string
  href: string
}

interface SitemapUrl {
  loc: string
  alternates?: AlternateLink[]
  // ...
}

const urls: SitemapUrl[] = [
  {
    loc: 'https://example.com/en/guide',
    alternates: [
      { hreflang: 'en', href: 'https://example.com/en/guide' },
      { hreflang: 'zh', href: 'https://example.com/zh/guide' }
    ]
  }
]

// 生成多语言 sitemap
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:xhtml="http://www.w3.org/1999/xhtml">
${urls.map(url => `  <url>
    <loc>${url.loc}</loc>
    ${url.alternates?.map(alt => 
      `<xhtml:link rel="alternate" hreflang="${alt.hreflang}" href="${alt.href}"/>`
    ).join('\n    ') || ''}
  </url>`).join('\n')}
</urlset>`

robots.txt 配置

txt
# docs/public/robots.txt
User-agent: *
Allow: /

Sitemap: https://your-domain.com/sitemap.xml

提交到搜索引擎

Google Search Console

  1. 登录 Google Search Console
  2. 添加站点验证
  3. 提交 sitemap:https://your-domain.com/sitemap.xml

Bing Webmaster Tools

  1. 登录 Bing Webmaster Tools
  2. 添加站点
  3. 提交 sitemap

百度站长平台

  1. 登录 百度站长平台
  2. 添加站点验证
  3. 提交 sitemap

自动提交

ts
// scripts/submit-sitemap.ts
import fetch from 'node-fetch'

const SITE_URL = 'https://your-domain.com'
const SITEMAP_URL = `${SITE_URL}/sitemap.xml`

// Google
async function submitToGoogle() {
  const url = `https://www.google.com/ping?sitemap=${encodeURIComponent(SITEMAP_URL)}`
  const res = await fetch(url)
  console.log('Google:', res.ok ? '✅ 成功' : '❌ 失败')
}

// Bing
async function submitToBing() {
  const apiKey = process.env.BING_API_KEY
  const url = `https://ssl.bing.com/webmaster/api.svc/json/SubmitUrl?apikey=${apiKey}&siteUrl=${SITE_URL}&url=${SITEMAP_URL}`
  const res = await fetch(url)
  console.log('Bing:', res.ok ? '✅ 成功' : '❌ 失败')
}

submitToGoogle()
submitToBing()

参考链接

贡献者

加载中...

想要成为贡献者?

在 CNB 上参与贡献