Files
easygoadmin-wiki/EasyGoAdmin_GoFrame_EleVue/搜索引擎优化 - 副本.txt
T
2026-10-26 09:07:19 +08:00

544 lines
28 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
================================================================================
EasyGoAdmin 文档站 SEO / GEO 更新标准
================================================================================
版本:1.0(2026-10-25)
适用:EasyGoAdmin_{Beego,Gin,GoFrame,Iris}_{AntdVue,EleVue,Layui,NaiveVue}
等 16 个 VitePress 文档子项目(结构高度同构,可直接照搬)
基线项目:EasyGoAdmin_GoFrame_EleVue
本文档定位:后续为其他项目做相同更新时的执行标准(审计清单 → 实施步骤 →
验收标准 → 移植注意事项)。
--------------------------------------------------------------------------------
第一部分:概念与目标
--------------------------------------------------------------------------------
1.1 SEO(Search Engine Optimization,搜索引擎优化)
面向传统搜索引擎(百度、Google、Bing)的爬虫与排序:
- 让爬虫能发现、抓取、理解每一个页面(技术 SEO)
- 让每个页面有独立、准确的标题与摘要(页面元数据)
- 让页面之间有清晰的权重传递结构(内链、面包屑、sitemap)
- 用结构化数据告诉搜索引擎"这是什么类型的内容"(JSON-LD)
1.2 GEO(Generative Engine Optimization,生成式引擎优化)
面向 AI 引擎(ChatGPT、Claude、Perplexity、豆包、Kimi、AI Overviews)
的爬虫与答案引用:
- 让 AI 爬虫明确被允许抓取(robots.txt 显式放行)
- 提供"给模型看的站点摘要"(llms.txt,llmstxt.org 标准)
- 页面内容"答案前置",首段即可被直接引用(:::tip 概述 首句)
- 结构化 Q/A(FAQPage JSON-LD)便于引擎抽取
- 时效信号(dateModified / sitemap lastmod)影响引用优先级
1.3 本方案的设计原则
a) 单一真相源:URL、站点描述、提取逻辑只写一处,多处复用。
b) 零运行时开销:全部在构建期(build)完成,不进客户端 bundle。
c) 零新依赖:只用 Node 内置模块 + VitePress 内置能力,
不新增 npm 包(llms.txt 脚本在 node_modules 缺失时也能跑)。
d) 内容不改版:不改动 143 篇正文的结构,SEO 增强全部在配置层注入。
--------------------------------------------------------------------------------
第二部分:审计清单(先查后改,逐项打勾)
--------------------------------------------------------------------------------
对目标项目执行以下检查(grep/ls 即可,全部只读):
[ ] 1. public/robots.txt 是否存在?
[ ] 2. public/sitemap.xml 或 vitepress sitemap 配置是否存在?
(查 .vitepress/config 中 grep "sitemap")
[ ] 3. public/llms.txt 是否存在?
[ ] 4. canonical 标签是否存在?(grep 'rel="canonical"' .vitepress/)
[ ] 5. og:image / og:title / JSON-LD 是否存在?
(grep 'og:image\|application/ld+json' .vitepress/)
[ ] 6. 页面级 frontmatter description 覆盖率?
(grep -rl "^description:" zh --include="*.md" | wc -l)
—— 若为 0,说明所有页面共用同一条 meta description(重复内容信号)
[ ] 7. <title> 是否带章节编号前缀?(看任意页 H1 形如 "5.10 字典模块")
[ ] 8. og:url 是否全站固定为首页地址?
[ ] 9. 是否有 404 页面?(ls 404.md)
[ ] 10. HTTPS 是否可用?
curl -sI https://<域名>/ -o /dev/null -w "%{http_code}"
curl 输出 000 或证书告警 → 说明证书不匹配,暂用 http
[ ] 11. 是否有站长平台验证 meta?(baidu-site-verification / google-site-verification)
[ ] 12. :::tip 概述 首句是否适合作为摘要?(抽查 10 页,看是否"答案前置")
[ ] 13. FAQ 类页面的 Q/A 格式是什么?(决定 extractFaqs 是否要加格式分支)
[ ] 14. 静态 twitter:image / og:image 指向的文件是否真实存在?
(Gin 项目 META_IMAGE="/social.png" 但 public/ 下无此文件 →
twitter:image 404,改为实际存在的 /logo.png)
[ ] 15. zh.ts 的 META_TITLE / META_DESCRIPTION 是否与项目技术栈一致?
(Gin 项目误写 "GoFrame v2",属元数据事实错误,一并修正)
审计结论示例(GoFrame_EleVue 基线,2026-10-25 实测):
robots/sitemap/llms/canonical/og:image/JSON-LD 全部缺失;
0/143 页有 description;143 页 title 全带编号;无 404;
HTTPS 证书为 CDN 默认证书(*.cdn.myqcloud.com)校验失败;
内容面强:141/143 页有 :::tip 概述、118 页有表格、139 页有代码块。
--------------------------------------------------------------------------------
第三部分:实施步骤(按序执行)
--------------------------------------------------------------------------------
步骤总览(7 步):
① 抽取共享层 extract.mjs → ② SEO 钩子 seo.ts → ③ 挂载到 config/index.ts
→ ④ titleTemplate → ⑤ robots.txt + 404.md → ⑥ llms.txt 脚本
→ ⑦ package.json 接线 + 生成
================================================================================
步骤 ①:共享提取层 .vitepress/config/extract.mjs(+ extract.d.mts)
================================================================================
新建纯 ESM、零依赖文件,被两类调用方复用:
- VitePress 配置(.ts,esbuild 打包时内联它)
- scripts/generate-llms-txt.mjs(Node 直接运行)
必须导出的五个符号:
1) SITE_URL —— 全站唯一 URL 真相源
canonical、og:url、twitter:url、JSON-LD、sitemap hostname、
llms.txt 链接、robots.txt 的 Sitemap 行全部由它派生。
格式:不带尾斜杠,如 "http://docs.goframe.elevue.easygoadmin.vip"
⚠ 若项目 HTTPS 可用必须用 https;证书有问题才暂用 http,
并在注释里写明"证书修复后只改这一处"。
2) SITE_DESCRIPTION —— 站点级描述(llms.txt 头部引用)
与 zh.ts 的 META_DESCRIPTION 保持一致(或让 zh.ts 直接 import 它)。
3) stripNumberPrefix(title)
剥离 <title> 中的章节编号前缀,关键词前置:
"5.10 字典模块" → "字典模块"
"K. 贡献指南" → "贡献指南"
正则(两分支缺一不可):
/^(?:\d+(?:\.\d+)+\s+|\d+\.\s+|[A-Z]\.\s+)/
分支说明:
- \d+(?:\.\d+)+\s+ 匹配 "5.10 " "1.6 "(数字.数字 + 空格)
- \d+\.\s+ 匹配 "1. "(单层数字 + 点 + 空格)
- [A-Z]\.\s+ 匹配 "A. " "K. "(附录字母编号)
⚠ 注意顺序与边界:不能误伤 "404 页面" 这类无编号标题
(要求编号后必须有点或已是 数字.数字 形态 + 空格)。
⚠ 只影响 <title> 和 JSON-LD headline 的 SEO 输出;
页内 H1 和侧边栏编号保持原样不动。
4) extractDescription(md) —— meta description / llms.txt 摘要的唯一来源
提取顺序:
a. 剥掉 frontmatter(/^---[\s\S]*?\n---\s*/)
b. 首选 :::tip 容器内正文:/^:::\s*tip[^\n]*\n([\s\S]*?)\n:::/m
(容器标签后缀不限定"概述",兼容 "说明"、"欢迎贡献" 等变体)
c. 回退到 H1 后第一个普通段落(跳过标题/容器/代码块/表格行)
d. 清洗:压缩空白、去行内 markdown(`code` **bold** [链接](url))
e. 截断:按中文句末标点(。!?!?)取首句,上限 100 字符;
截断处避免切碎词(去掉末尾不完整词)
输出单行纯文本;失败返回 ""(调用方应回退到站点级描述)。
5) extractFaqs(md) —— FAQPage JSON-LD 的 Q/A 提取
支持两种站内常见格式(按需增删分支):
格式 A(标题式):### Q:问题\n答案… (切块后答案截到下一个标题)
格式 B(加粗式):**Q:问题**\n答案… (答案截到下一个 Q 或标题)
共同点:
- Q/A 文本统一走 cleanText:去代码围栏行、行内 code/bold/链接、压空白
- 只在命中 ≥1 组时返回,调用方据此决定是否注入 FAQPage
⚠ 若目标项目的 FAQ 是表格形式(| 症状 | 原因 |),不产出 Q/A,
就不要强行转换——JSON-LD 必须与页面可见内容一致。
同目录新建 extract.d.mts(TypeScript 类型声明,供编辑器识别):
export declare const SITE_URL: string;
export declare const SITE_DESCRIPTION: string;
export declare function stripNumberPrefix(title: string): string;
export declare function extractDescription(md: string): string;
export declare function extractFaqs(md: string): { q: string; a: string }[];
⚠ 关键坑(本项目实测踩过):
注释里不要出现序列 "*/"。形如 zh/**/*.md 的路径写在块注释中,
其中的 "**/*" 会提前终止注释导致 SyntaxError。
改写为 "zh 目录下全部 Markdown" 之类的描述。
================================================================================
步骤 ②:SEO 钩子 .vitepress/config/seo.ts
================================================================================
导出 createSeoHooks(sidebar),返回三个 VitePress 构建钩子。
入参传 zhConfig.themeConfig?.sidebar —— 面包屑结构从侧边栏自动派生,
侧边栏改了面包屑自动跟随,无需第二份清单。
--------------------------------------------------------------------------------
2.1 transformPageData(pageData, ctx) —— 页面级 title / description
--------------------------------------------------------------------------------
对每页返回增量对象(VitePress 自动 merge):
- title: stripNumberPrefix(pageData.title)
(pageData.title 已由 VitePress 从 H1/frontmatter 推导)
- description: extractDescription(读取 pageData.relativePath 对应源文件)
仅当页面没有 frontmatter.description 且提取非空时设置;
提取失败保持 "" → 渲染时自动回退站点级描述。
读文件:fs.readFileSync(path.resolve(ctx.siteConfig.srcDir, relativePath))
效果:
<title>5.10 字典模块 | EasyGoAdmin</title>
→ <title>字典模块 | EasyGoAdmin 开发文档</title>
<meta name="description"> 全站统一文案
→ 每页独立(取该页 tip 首句)
--------------------------------------------------------------------------------
2.2 transformHead(ctx) —— canonical / OG / twitter / JSON-LD
--------------------------------------------------------------------------------
入参 ctx 含:pageData、title(已拼模板)、description、content(渲染后 HTML)、
siteConfig(root/srcDir)。
前置判断:relativePath 为空或 === "404.md" → 返回 [](404 不做 SEO)。
注入的标签清单(13 项 + 1 个 JSON-LD script):
["link", { rel: "canonical", href: url }] ← 每页独立 canonical
og:type (首页 website,内容页 article)
og:site_name "EasyGoAdmin"(按项目改)
og:locale "zh_CN"
og:title (用去编号后的页标题)
og:description (用步骤①提取的 description)
og:url (= canonical)
og:image (SITE_URL + /logo.png,必须绝对地址)
twitter:title / twitter:description / twitter:url / twitter:image
["script", { type: "application/ld+json" }, json] ← 见 2.3
URL 推导:
index.md → SITE_URL + "/"
404.md → 跳过
其他 → SITE_URL + "/" + relativePath 换 .html 后缀
(cleanUrls 关闭时正文页带 .html,与侧边栏链接一致)
⚠ 与静态 head 的去重机制:
VitePress mergeHead 按 meta 标签的"第一个属性值"判重
(property:"og:url" 视为同一 key)。因此:
- 静态 head 里的 og:url/og:description/twitter:* 会被本钩子的
同 key 输出覆盖(构建期),无需手动删除静态项;
- 静态 twitter:card(本钩子不输出)会保留 —— 正确行为。
⚠ 本钩子是 build-only("runs before writing HTML to dist"),
dev server 页面上看不到这些标签是正常的,用 docs:build 验收。
--------------------------------------------------------------------------------
2.3 JSON-LD 结构化数据(单 script,顶层对象或数组)
--------------------------------------------------------------------------------
统一转义:JSON.stringify(...).replace(/</g, "\\u003c")
(防止内容中出现 </script> 破坏注入;< 在 JSON 字符串内合法。)
【首页 index.md】
1. WebSite:name、url、inLanguage、description
2. Organization:name、url(官网)、logo、sameAs(Gitee 仓库 + 官网)
【内容页】
1. TechArticle:
headline = 页面 H1 纯文本(去编号!与 <title> 一致,关键词前置;
提取顺序:源 Markdown H1 → 渲染 HTML <h1> → 兜底 title)
description、url(= canonical)、inLanguage: "zh-CN"
mainEntityOfPage: { @type: WebPage, @id: url }
publisher: Organization 引用
dateModified: git 最后提交时间(见 2.4,无则省略字段)
2. BreadcrumbList(侧边栏派生):
itemListElement = [
{ position:1, name:"首页", item: SITE_URL + "/" },
...章节链(每级 name=去 emoji 的侧边栏文案),
末级 { name: 页面名, item: 当前页 url }
]
中间章节级无自己 URL → 只给 name 不给 item(schema.org 合法)。
侧边栏文案去前导 emoji:/^[^\p{L}\p{N}]+/u 清洗。
3. FAQPage(仅当 extractFaqs 命中):
mainEntity = [{ @type:Question, name:Q,
acceptedAnswer:{ @type:Answer, text:A } }]
⚠ Google 已收窄 FAQ 富结果资格,但 JSON-LD 对 GEO(AI 抽取)
仍然有效,且必须与页面可见 Q/A 一致。
--------------------------------------------------------------------------------
2.4 git 时间线(dateModified + sitemap lastmod 共用)
--------------------------------------------------------------------------------
单次 git 命令构建全量映射(避免每页一次进程开销):
git log --format=:::%cI --name-only --relative -n 500 -- .
cwd = 项目根(ctx.siteConfig.root)
解析:以 ":::" 开头的行是提交时间(ISO 8601),
其后普通行是文件路径(git log 新→旧,首见即最新);
key = 相对路径(--relative 保证与 pageData.relativePath 同形)。
降级策略:git 不可用 / 文件无提交记录 → 静默省略 lastmod/dateModified,
不阻塞构建。模块级缓存 Map,整个 build 只跑一次。
--------------------------------------------------------------------------------
2.5 sitemap = { hostname, transformItems }
--------------------------------------------------------------------------------
VitePress 1.x 内置 sitemap 选项(config 顶层):
sitemap: {
hostname: SITE_URL,
transformItems(items) {
// ⚠ 关键实测(Gin_EleVue 首次构建暴露):
// transformItems 收到的 item.url 是【相对路径】——
// "404.html"、"zh/core/dict.html"、""(首页),
// 无前导斜杠、无域名;hostname 是之后 SitemapStream 才拼的。
// 所以 endsWith("/404.html") 永远不命中(冒烟测试若用完整
// URL 传参会产生假阳性!测试必须模拟真实形态)。
// 1) 过滤 404:/(^|\/)404\.html$/.test(item.url) → 丢弃
// 2) 过滤 README:仓库根 README.md 会被 vitepress 当页面收录
// (README.html 不在侧边栏、属仓库自述),同样 /^...README\.html$/ 过滤
// 3) url → 相对路径反推:去尾 .html 加 .md;
// "" 或 "index.html" → "index.md"
// 4) 查 git 映射注入 lastmod;查不到保持原样
// (部分新文件/未提交文件无 lastmod 属正常降级,
// Gin 实测 154 条中 126 条有 lastmod)
}
}
产出:构建后 dist/sitemap.xml(dev 模式不存在,属正常)。
================================================================================
步骤 ③:挂载到 .vitepress/config/index.ts
================================================================================
import { createSeoHooks } from "./seo";
const seo = createSeoHooks(zhConfig.themeConfig?.sidebar);
export default defineConfig({
...sharedConfig,
transformPageData: seo.transformPageData,
transformHead: seo.transformHead,
sitemap: seo.sitemap,
...
});
⚠ createSeoHooks 必须在模块顶层调用(sitemap.transformItems 无 ctx,
依赖 transformPageData 先把 projectRoot 记下来;兜底 process.cwd())。
================================================================================
步骤 ④:titleTemplate(config/shared.ts)
================================================================================
export const sharedConfig = defineConfig({
title: "EasyGoAdmin",
titleTemplate: "EasyGoAdmin 开发文档", ← 新增
...
});
效果:<title>字典模块 | EasyGoAdmin 开发文档</title>
机制:VitePress createTitle 中 页面 frontmatter.titleTemplate 优先,
其次站点级 titleTemplate,最后兜底 " | 站点title"。
首页 index.md 自带 titleTemplate(frontmatter)→ 不受影响。
⚠ 站点名若与 titleTemplate 相同会被去重(createTitleTemplate 的
siteTitle === template 分支),保持两者不同。
================================================================================
步骤 ⑤:robots.txt + 404.md
================================================================================
【public/robots.txt】(静态文件,直接进 dist)
User-agent: *
Allow: /
# 显式放行生成式引擎 / AI 爬虫(GEO)
User-agent: GPTBot
Allow: /
User-agent: ChatGPT-User
Allow: /
User-agent: ClaudeBot
Allow: /
User-agent: Claude-Web
Allow: /
User-agent: anthropic-ai
Allow: /
User-agent: PerplexityBot
Allow: /
User-agent: Google-Extended
Allow: /
User-agent: Bytespider
Allow: /
User-agent: bingbot
Allow: /
Sitemap: <SITE_URL>/sitemap.xml
⚠ Sitemap 行的地址必须与 extract.mjs 的 SITE_URL 一致(手工同步)。
【404.md】(项目根目录,VitePress 自动识别为 404 页)
---
head:
- - meta
- name: robots
content: noindex
---
# 页面不存在
抱歉,您访问的页面不存在或已被移动。
[返回首页](/) · [浏览文档](/zh/introduction)
⚠ 首个 frontmatter head 例外:正文页约定"无 frontmatter",
404 页因需要 noindex 豁免。
⚠ 链接风格与全站一致(站内相对/根路径),死链检查才能通过。
================================================================================
步骤 ⑥:llms.txt 生成脚本 scripts/generate-llms-txt.mjs
================================================================================
零依赖 Node 脚本,import extract.mjs 复用 SITE_URL/SITE_DESCRIPTION/
extractDescription(与 meta description 同源,绝不手写两份摘要)。
流程:
1. 递归收集 zh/ 下全部 .md(排除 404,404 不在 zh/ 天然排除)
2. 每页取:首个 H1(保留编号,便于 AI 理解章节位置)
extractDescription 首句(作为条目摘要)
url = SITE_URL + /zh/<相对路径>.html
3. 按顶层目录映射到侧边栏章节分组(SECTIONS 常量数组,
与 config/zh.ts 的侧边栏章名保持一致;映射不到的目录兜底"附录")
4. 组内按 H1 编号排序(数字分支按数值、字母分支按码点、无编号最后)
5. 输出 llmstxt.org 标准格式:
# <站点标题>
> <SITE_DESCRIPTION>。<能力一句话>。本文档共 N 篇,按章节组织。
## <章节名>
- [H1](url): 首句摘要
...
6. 写入 public/llms.txt,stdout 打印页数/章节数
⚠ 同一章节名可能由多个目录合并(如 appendix + other 同为"附录"),
输出时按 label 去重只打印一次。
⚠ 脚本内不要在块注释写 "zh/**/*.md"(见步骤①的 */ 坑)。
================================================================================
步骤 ⑦:package.json 接线 + 首次生成
================================================================================
"scripts": {
"docs": "vitepress dev .",
"docs:llms": "node scripts/generate-llms-txt.mjs",
"docs:build": "node scripts/generate-llms-txt.mjs && vitepress build .",
"docs:preview": "vitepress preview ."
}
- docs:build 前置生成 llms.txt(保证部署产物永远最新)
- 新增/改名页面后若只要刷新索引:yarn docs:llms
- ⚠ Windows 下 yarn(cmd)执行 "A && B" 可用;不要改成分号。
--------------------------------------------------------------------------------
步骤 ⑧(收尾):更新 CLAUDE.md
--------------------------------------------------------------------------------
把以下约定写进项目 CLAUDE.md,防止后续改动破坏 SEO:
1. :::tip 首句 = meta description + llms.txt 条目,须"答案前置"。
2. 编号冻结:章节编号同时被侧边栏、正文互引("详见 5.10")、
JSON-LD 面包屑、llms.txt、外链锚文本引用 —— 发布后禁止重排。
3. 新增页面的 checklist:写 H1 编号 → 加 tip 概述 →
zh.ts 侧边栏登记 → (可选)yarn docs:llms。
4. 记录 SEO 工具链位置与 SITE_URL 单点修改约定。
--------------------------------------------------------------------------------
第四部分:验收标准
--------------------------------------------------------------------------------
A. 无 node_modules 的快速冒烟(Node ≥ 22.18,type stripping)
node --experimental-strip-types -e "
import('./.vitepress/config/seo.ts').then(async ({ createSeoHooks }) => {
const zh = await import('./.vitepress/config/zh.ts');
const h = createSeoHooks(zh.zhConfig.themeConfig?.sidebar);
console.log(typeof h.transformPageData, typeof h.transformHead, typeof h.sitemap);
})"
B. 完整验收(需 yarn install 后)
1) yarn docs:build 无报错(死链检查通过)
2) dist/sitemap.xml 存在,含 lastmod,无 404.html 与 README.html 条目
(lastmod 覆盖率允许 <100%:未提交的新文件无 git 记录,属正常降级)
3) dist/robots.txt、dist/llms.txt 存在
4) 抽查任意内容页 dist/zh/xxx.html 的 <head>:
- <title> 无编号前缀、带 titleTemplate 后缀
- <meta name="description"> 是该页 tip 首句(非全站统一文案)
- <link rel="canonical"> 指向本页完整 URL
- og:title/og:description/og:url/og:image 与页面一致且 URL 为绝对地址
- <script type="application/ld+json"> 可被 JSON.parse,
含 TechArticle + BreadcrumbList(FAQ 页多 FAQPage)
- TechArticle.headline 与页面 H1 一致(或至少无编号差异过大)
5) 首页含 WebSite + Organization
6) 404.html 含 noindex,且不出现在 sitemap
7) llms.txt 条目数 == zh 下 md 文件数,链接可访问
8) 用浏览器扩展(如 JSON-LD Viewer)验证结构化数据无报错
C. 提交前人工项(脚本做不了)
1) 百度/Google 站长平台验证 meta(拿到验证码后加进 shared/zh head)
2) 百度站长"主动推送"提交首页(百度对 sitemap 支持弱,主动推送是主收录手段)
3) HTTPS 证书修复后:改 extract.mjs 的 SITE_URL + zh.ts 的 META_URL,
robots.txt 的 Sitemap 行同步,重新 docs:build
--------------------------------------------------------------------------------
第五部分:移植到其他 15 个项目时的差异点
--------------------------------------------------------------------------------
同构不变量(直接照搬):
- extract.mjs / extract.d.mts / seo.ts / generate-llms-txt.mjs
四个文件整体复制(它们不依赖具体侧边栏内容,sidebar 以参数传入)
- index.ts 挂载三行、shared.ts titleTemplate、package.json 三行脚本
- robots.txt / 404.md 模板
必须按项目修改的点(清单):
[ ] SITE_URL:每个子域不同(docs.gin.elevue.... / docs.beego.layui....)
[ ] SITE_DESCRIPTION / titleTemplate / og:site_name:若各项目文案不同
[ ] extract.mjs 中 Organization 的 url/sameAs:仓库地址不同
(EasyGoAdmin_Gin_EleVue → 对应 Gitee 仓库路径)
[ ] scripts/generate-llms-txt.mjs 的 SECTIONS 目录→章节映射:
核对目标项目的 zh/ 顶层目录与侧边栏章名(各前端/后端组合
章节编号可能不同,以该项目 zh.ts 侧边栏为准)
[ ] extractFaqs 的 Q/A 格式分支:先抽查目标项目 FAQ 页格式,
表格式 FAQ 不要强转
[ ] robots.txt 的 Sitemap 行域名
[ ] llms.txt 头部章节数 N 是脚本自动统计,无需手改
[ ] 404.md 内的示例链接指向目标项目实际存在的首页/入门页
[ ] zh.ts 若有静态 og/twitter meta,确认与 transformHead 输出
key 一致会被覆盖(一般无需删;不放心可删掉静态项)
版本差异注意:
- VitePress 需 ≥ 1.0(transformPageData/transformHead/sitemap 选项
1.x 均有;本方案在 1.3.4 实测)。若他项目版本更老,先核对
node_modules/vitepress/dist/node/index.d.ts 中是否存在
sitemap / transformHead / transformPageData 三个字段。
- 侧边栏结构假设为 { "/zh/": [ {text, items:[{text,link}|{text,items}]} ] }
的标准 DefaultTheme 形态;若他项目 sidebar 是数组形态或
多语言 key 不同("/en/"),buildCrumbMap 已兼容数组入参,
但 key 需与路由前缀一致(当前写死 "/zh/",改多语言时参数化)。
--------------------------------------------------------------------------------
第六部分:实测数据与已知限制(基线项目)
--------------------------------------------------------------------------------
实测(2026-10-25,GoFrame_EleVue):
- llms.txt:143 页 / 13 章节 / 32KB,生成耗时 < 1s
- 冒烟测试:13 个 head 标签注入、TechArticle+BreadcrumbList
(首页 > 5. 核心功能 > 数据与配置 > 5.10 字典模块)、
FAQPage 24 问(appendix 加粗式)/ 18 问(quickstart 标题式)、
git dateModified 与 sitemap lastmod 正常、404 跳过、
sitemap 过滤 404 —— 全部通过
移植实测(2026-10-25,EasyGoAdmin_Gin_EleVue,按本标准全流程执行):
- 审计:与基线同构缺失;额外发现 META_IMAGE 指向不存在的 social.png、
META_TITLE/META_DESCRIPTION 误写 GoFrame、HTTPS 同样证书不匹配
- 差异点仅 6 处:SITE_URL、Gitee 仓库地址、SITE_DESCRIPTION/META 文案、
llms 脚本标题行、robots Sitemap 行、(复核)SECTIONS 章节映射
——zh/ 目录结构与侧边栏章节与基线完全一致,映射无需改动
- FAQ 4 个页全为 **Q:** 加粗式(基线为两种混用),既有 extractFaqs 直接命中
- 完整构建验收(yarn docs:build,21s):
sitemap 154 条(过滤 404+README 后)、lastmod 126/154、
内容页 title/canonical/OG/JSON-LD 全通过、
首页 WebSite+Organization、404 noindex 且不入 sitemap、
llms.txt 153 条 == zh 下 md 数、FAQPage 11 问
- 首次构建暴露 transformItems 相对路径坑(见 2.5),修复后复验通过
已知限制:
1. HTTPS:docs 子域 443 返回腾讯 CDN 默认证书(*.cdn.myqcloud.com),
curl 校验失败,全站暂用 http。修复后按步骤⑦-C3 单点切换。
2. transformHead/transformHead/sitemap 均为 build-only,
dev server 下看不到增强标签,验收必须以 docs:build 产物为准。
3. og:image 用的 logo.png(方形),非 1200×630 社交卡片尺寸 ——
可后续出专用卡片图后只改 og:image 一处。
4. 百度/Google 站长验证与主动推送需要平台账号,未包含在本方案。
5. 站点验证 meta 未加(无验证码);若后续加,放 shared.ts head。
6. 未启用 VitePress lastUpdated 主题显示(与 SEO 无关,另议)。
--------------------------------------------------------------------------------
附录:一页速查(执行顺序)
--------------------------------------------------------------------------------
1. 跑第二部分审计清单,记录结论
2. 复制/调整 extract.mjs + extract.d.mts(改 SITE_URL 等 9 个差异点)
3. 复制 seo.ts,核对 FAQ 格式分支与侧边栏 key
4. index.ts 挂 3 行;shared.ts 加 titleTemplate
5. 放 robots.txt(改域名)+ 404.md(改链接)
6. 复制 generate-llms-txt.mjs(核对 SECTIONS 映射)→ yarn docs:llms
7. package.json 改 3 行脚本
8. yarn install && yarn docs:build,按第四部分 B 逐项验收
9. 更新该项目 CLAUDE.md(tip 首句约定 + 编号冻结)
10. 站长平台验证/推送(人工)
(完)