diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index ec37a0d..f608d91 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -12,6 +12,22 @@ const isEdgeOne = !!process.env.EDGEONE || process.env.EDGEONE === '1' // 3. 否则(如 GitHub Pages),使用 '/easy-vibe/' const base = process.env.BASE || (isVercel || isEdgeOne ? '/' : '/easy-vibe/') +// 站点 URL 配置 - 根据部署环境动态确定 +const getSiteUrl = () => { + if (isVercel && process.env.VERCEL_URL) { + return `https://${process.env.VERCEL_URL}` + } + if (isEdgeOne && process.env.EDGEONE_URL) { + return `https://${process.env.EDGEONE_URL}` + } + if (process.env.SITE_URL) { + return process.env.SITE_URL + } + return 'https://datawhalechina.github.io/easy-vibe' +} + +const siteUrl = getSiteUrl() + // 语言映射配置 const localeMap = { 'zh-cn': { @@ -79,9 +95,6 @@ const localeMap = { // SEO 相关配置 const getSeoHead = (locale, title, description, path = '') => { const seoConfig = localeMap[locale] || localeMap['zh-cn'] - const siteUrl = isVercel - ? 'https://your-project.vercel.app' - : 'https://datawhalechina.github.io/easy-vibe' const canonicalUrl = path ? `${siteUrl}${path}` : `${siteUrl}/${locale}/` const ogImageUrl = `${siteUrl}${base}logo.png` @@ -172,10 +185,41 @@ const getSeoHead = (locale, title, description, path = '') => { '@type': 'ImageObject', url: ogImageUrl } + }, + mainEntity: { + '@type': 'Course', + name: title, + description: description, + provider: { + '@type': 'Organization', + name: 'Datawhale', + sameAs: 'https://github.com/datawhalechina/easy-vibe' + } } } head.push(['script', { type: 'application/ld+json' }, JSON.stringify(jsonLd)]) + // 添加 BreadcrumbList 结构化数据 + const breadcrumbJsonLd = { + '@context': 'https://schema.org', + '@type': 'BreadcrumbList', + itemListElement: [ + { + '@type': 'ListItem', + position: 1, + name: '首页', + item: siteUrl + }, + { + '@type': 'ListItem', + position: 2, + name: locale === 'zh-cn' ? '教程' : 'Tutorial', + item: `${siteUrl}/${locale}/` + } + ] + } + head.push(['script', { type: 'application/ld+json', class: 'breadcrumb-jsonld' }, JSON.stringify(breadcrumbJsonLd)]) + return head } @@ -1053,12 +1097,20 @@ export default defineConfig({ // Sitemap 配置 sitemap: { - hostname: 'https://datawhalechina.github.io/easy-vibe', + hostname: siteUrl, + changefreq: 'weekly', + priority: { + '/': 1.0, + '/zh-cn/': 0.9, + '/zh-cn/stage-0/': 0.9, + '/zh-cn/stage-1/': 0.8, + '/zh-cn/stage-2/': 0.8, + '/zh-cn/stage-3/': 0.8, + '/zh-cn/appendix/': 0.7 + }, transformItems(items) { - // 过滤掉旧版内容和未完成的语言版本 return items.filter((item) => { const url = item.url - // 排除旧版内容目录 if ( url.includes('/extra/') || url.includes('/examples/') || @@ -1066,12 +1118,43 @@ export default defineConfig({ ) { return false } - // 包含所有语言版本 return true }) } }, + // 构建结束时动态生成 robots.txt + async buildEnd(siteConfig) { + const fs = await import('fs') + const path = await import('path') + + const robotsTxt = `# https://www.robotstxt.org/robotstxt.html +User-agent: * +Allow: / + +# 禁止搜索引擎抓取旧版内容(已迁移到新目录结构) +Disallow: /zh-cn/extra/ +Disallow: /zh-cn/examples/ +Disallow: /zh-cn/project/ +Disallow: /en/extra/ +Disallow: /en/examples/ +Disallow: /en/project/ + +# 禁止抓取 VitePress 缓存和构建文件 +Disallow: /.vitepress/ +Disallow: /@fs/ + +# Sitemap 位置 +Sitemap: ${siteUrl}/sitemap.xml +` + + const outDir = siteConfig.outDir || path.resolve(__dirname, '.vitepress/dist') + const robotsPath = path.join(outDir, 'robots.txt') + + fs.writeFileSync(robotsPath, robotsTxt, 'utf-8') + console.log('✓ Generated robots.txt with sitemap URL:', `${siteUrl}/sitemap.xml`) + }, + // 多语言配置 - 使用 cn/en-us/ja 结构 locales: { // 根路径 — 仅用于 404 页面兜底,实际首页由 docs/index.md 自动重定向 diff --git a/docs/public/robots.txt b/docs/public/robots.txt deleted file mode 100644 index bb19b30..0000000 --- a/docs/public/robots.txt +++ /dev/null @@ -1,18 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Allow: / - -# 禁止搜索引擎抓取旧版内容(已迁移到新目录结构) -Disallow: /zh-cn/extra/ -Disallow: /zh-cn/examples/ -Disallow: /zh-cn/project/ -Disallow: /en/extra/ -Disallow: /en/examples/ -Disallow: /en/project/ - -# 禁止抓取 VitePress 缓存和构建文件 -Disallow: /.vitepress/ -Disallow: /@fs/ - -# Sitemap 位置 -Sitemap: https://datawhalechina.github.io/easy-vibe/sitemap.xml.gz diff --git a/vercel.json b/vercel.json index e58e5a8..a2849cc 100644 --- a/vercel.json +++ b/vercel.json @@ -2,5 +2,50 @@ "buildCommand": "npm run build", "installCommand": "npm install", "framework": "vitepress", - "outputDirectory": "docs/.vitepress/dist" + "outputDirectory": "docs/.vitepress/dist", + "headers": [ + { + "source": "/(.*)", + "headers": [ + { + "key": "X-Content-Type-Options", + "value": "nosniff" + }, + { + "key": "X-Frame-Options", + "value": "DENY" + }, + { + "key": "X-XSS-Protection", + "value": "1; mode=block" + }, + { + "key": "Referrer-Policy", + "value": "strict-origin-when-cross-origin" + }, + { + "key": "Permissions-Policy", + "value": "camera=(), microphone=(), geolocation=()" + } + ] + }, + { + "source": "/sitemap.xml", + "headers": [ + { + "key": "Cache-Control", + "value": "public, max-age=86400, s-maxage=86400" + } + ] + }, + { + "source": "/robots.txt", + "headers": [ + { + "key": "Cache-Control", + "value": "public, max-age=86400, s-maxage=86400" + } + ] + } + ] }