Skip to content

LV112-自动侧边栏的限制与避坑

本文是自动侧边栏系列最后一篇,汇总配置时"不看源码不知道"的限制:生成时机、忽略机制、命名约定匹配、排序规则,以及 README 与实际实现之间的偏差清单。前四篇见 总览配置详解filePath 模式rewrites 模式

一、生成时机限制

1. 启动时一次性生成

数据生成只发生在 Vite config() 钩子里,闭包变量 isExecute 保证 dev + build 全程只执行一次。因此运行期间的一切文件变动(新增、删除、改名、移动、改 frontmatter 标题)都不会反映到导航/侧边栏,必须重启 dev 服务或重新 build。改了文档标题侧边栏没变、新加的文档侧边栏没有,先重启再说。

2. restart 配置项无效

SidebarOption 类型里声明了 restart?: boolean("md 创建或删除时是否重启服务"),但 auto-nav-sidebar 没有实现对应的 configureServer 监听——这个能力只在 sidebar-resolve 版插件里存在(watcher 监听 md 增删后调 restart())。在 mist 主题下配置它没有任何效果。

3. 路径不存在时的静默兜底

扫描目录不存在时,插件不会报错,而是注入一份内置的测试数据createTestSidebarData 里写死的 Guide/Config 等英文示例)。看到侧边栏出现一堆无关的英文条目,第一反应应该是:path 配错了或目录被移动了。

二、忽略机制

1. 默认黑名单只增不减

侧边栏与导航栏都固定忽略 ["node_modules", "dist", ".vitepress", "public"],用户 ignoreList追加合并([...DEFAULT_IGNORE_DIR, ...ignoreList])。没有配置项能把默认目录从黑名单里捞出来——比如想在 public 旁放文档目录,只能换名字。

2. 匹配的是名字不是路径

ignoreList 与黑名单都按条目名精确匹配(正则则 test 名字),不是路径匹配。ignoreList: ["test"] 会忽略每一层叫 test 的目录;想只忽略某一层的,用正则配合完整文件名,或用 beforeCreateSidebarItems 钩子按需过滤。

3. index.md 的三重开关

(1)根目录 index.md:scannerRootMd 分支里永远排除;

(2)各目录 index.md:mist 默认 ignoreList: ["index.md", "README.md"] 排除;不配置则目录页会以"目录名"为标题出现在侧边栏;

(3)ignoreIndexMd: true:再显式排除一层(含 .MD 大写扩展名)。

三、命名约定匹配限制

这是对 mist 文档库影响最大的一节。插件的序号体系是为 01.标题.md(数字 + 点分隔)设计的,而 mist 库统一用 LVxxx-标题.mdNN-中文目录(连字符),两套约定并不匹配:

1. 序号解析不认识连字符

resolveFileName 只按点(或 indexSeparator 自定义分隔符)切序号。LV001-pnpm工作区.md 解析不出数字序号 → 进无序号队列、sort 值取缺省 9999;01-开发 目录名解析不出 01 → 侧边栏目录文本原样带 01- 前缀(实测如此,本站侧边栏显示的就是 01-独立插件包)。

2. 排序侥幸正确的原因

无序号条目按 readdirSync 返回顺序进入稳定排序,readdirSync 在 Windows/Linux 上都近似字母序,而 LV001 < LV004 < LV007三位零填充字典序恰好等于数值序——这正是库规范强制 LVxxx 三位宽度的原因之一。一旦出现两位编号(LV99 与 LV100 混排)字典序就错乱。

3. 想要正确行为的两条路

(1)用回点分隔命名01.标题.md):序号、标题剥离全部生效,但与库规范冲突,不推荐;

(2)frontmatter sidebarSort:给关键文档手工设排序值,或开启 sortNumFromFileName(但连字符命名解析不出序号,对 mist 库无效)。目录标题想去掉 01- 前缀,可开 titleFormMd: true 让标题取自各目录 index.md 的 frontmatter title(tdoc 生成的目录页 title 恰好是去掉序号的目录名),代价是文章标题也会转而读 md 一级标题。

4. 同名 md 抑制是隐藏行为

目录旁边存在同名 md(01-开发/01-开发.md 并存)时,目录节点被跳过。误创建同名文件会让整个目录从侧边栏消失,且只有一条不起眼的逻辑分支,排查时不容易想到。

四、排序与序号规则

(1)同序号覆盖:同一层两个文件解析出相同序号(点分隔命名下),后处理的覆盖先处理的,仅有一条警告;

(2)fileIndexPrefix 默认关闭:类型与 README 里"默认 true"不一致(见第六节),序号非法只有警告不拦截;

(3)sort 的性能账sort: true 时每个 md 都要 readFileSync + gray-matter 解析。文档量大(几百篇)时启动耗时增加明显,纯靠文件名字典序排序的库可以关掉它换启动速度;

(4)无序号垫底:解析不出序号的条目永远排在有序号条目之后(sidebarItemsNoIndex 拼接在尾部)。

五、结构与功能限制

1. 多语言未实现

SidebarOption.localeRootDir、locales 相关的类型定义继承自 sidebar-resolve,但 auto-nav-sidebar 的 config 钩子里没有任何 locales 分支——配置了国际化的站点,各语言的侧边栏会拿到同一份数据。需要多语言侧边栏时只能用 sidebar-resolve 版插件。

2. 侧边栏 key 依赖一级目录的同前缀

rewrites 模式下侧边栏 key 取重写值的第二段,默认同一目录下所有文件的重写前缀一致sdoc/plugin/...)。某目录下混入不同前缀的重写规则时,key 互相覆盖,部分侧边栏丢失。sidebar-resolve 提供的 checkRewritesPrefix 校验在 auto-nav-sidebar 里没有接线(类型里有、代码不读)。

3. 中文 URL 与部署环境

filePath 模式的链接带中文与空格,部署到部分静态托管(Nginx 未配编码、对象存储等)时可能 404。VitePress 内部会 encodeURI,一般场景可用,但对外分享链接不友好——这是切到 rewrites 模式(permalink 全英文)的主要动机之一。

4. 注入只认对象或数组

type: "object" 时手写 sidebar 必须也是对象,type: "array" 时必须是数组,类型不符时手写部分被丢弃(只有一条告警)。混合场景先确认手写数据的形态。

六、README 与实现的差异清单

文档(README / 类型注释)与代码行为有出入的地方,配置时以本清单为准:

条目文档说法实际行为
fileIndexPrefix 默认值README 表格写 true代码默认 false(序号非法仅警告)
collapsed 默认值README 表格写 true代码默认 undefined(不折叠)
resolveRule类型里有、Teek README 详述auto-nav-sidebar 不读此配置,模式由 __create__ 标记自动判定
restart类型注释"md 增删时重启"未实现(仅 sidebar-resolve 有)
checkRewritesPrefix类型里有未接线,配置无效
localeRootDir / locales类型里有未实现,多语言不生效
nav-sidebar 的 getNavData(config, docsRoot)README 示例带第二个路径参数函数签名只收一个参数,第二个被忽略;根目录实际取 process.cwd() + rootDir
nav-sidebar 的序号剥离README 提到带序号文件排序仅识别 ^[0-9]{2}- 两位数字 + 连字符,三位 LV001- 不剥离

注意

排查侧边栏问题的通用顺序:先 debugInfo: true 确认模式判定 → 再 saveToFile: true 拿到完整生成数据对照预期 → 最后对照本清单检查是不是踩了命名或时机限制。