恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
VuePress多侧边栏配置详解:按目录拆分导航的完整实践
首页
资讯中心
/
VuePress多侧边栏配置详解:按目录拆分导航的完整实践
VuePress多侧边栏配置详解:按目录拆分导航的完整实践
发布时间:2026/10/14 12:33:47
很多朋友用 VuePress 做个人博客或团队文档站一开始图省事都在themeConfig.sidebar里甩一个数组文章少的时候确实没什么感觉。等文档写到上百篇问题马上就来了所有文章挤在同一个侧边栏里找一篇老文章得翻半天不同模块的内容混在一起整个侧边栏又长又乱。这时候你就会意识到VuePress 其实是可以按照目录或路径生成多个侧边栏的而且配置方式并不复杂只是官方文档里写得比较分散不少人都没注意到。这篇内容我结合自己做某个文档站项目的实际过程把 VuePress 生成多个侧边栏的几种做法、背后的匹配规则、我踩过的坑以及几个辅助配置都完整过一遍。无论你是刚搭好博客的新手还是已经在维护一个体量不小的文档站这个配置都能让侧边栏看起来清爽不少也方便后续扩展内容模块。1. 为什么要拆多个侧边栏1.1 单一侧边栏的典型痛点先说我遇到的实际场景。当时我把站点目录分为两块一块放工具类的操作文档比如安装、配置、接口说明另一块是日常记录的博客文章。最开始用单一 sidebar 数组配置结构大概是// .vuepress/config.js module.exports { themeConfig: { sidebar: [ /guide/, /guide/install, /guide/config, /blog/2025/01/xxx, /blog/2025/02/xxx ] } }这种写法有两个明显问题。第一侧边栏把所有页面平铺成一个列表没有分组概念用户想找某篇具体文章必须靠眼睛扫。文章超过四五十篇之后这种体验基本等于灾难。第二不同分类的内容混在一起用户进入“文档区”时看到博客链接进入“博客区”时又看到文档链接心智负担很重。用户在一个模块里侧边栏就应该只展示和当前模块相关的内容。单一 sidebar 数组适合的就是那种小站点比如只有十几个页面的项目说明文档或者一个只有几篇文章的个人主页。一旦内容开始分类就一定要拆成多个侧边栏。1.2 多个侧边栏的三种实现思路VuePress 1.x 的默认主题里sidebar 配置项一共可以接收三种形态的数据数组整个站点所有页面共用同一个侧边栏适合小型站点。对象对象的键是路径前缀对应不同的侧边栏配置这是实现多个侧边栏的核心方式。函数根据当前页面的路径动态计算返回侧边栏配置适合需要更动态控制的情况。其中对象形态是最常用、也最好理解的写法。它的基本逻辑是路径前缀到侧边栏配置的映射。只要页面路径命中了某个键就使用这个键对应的侧边栏。举个例子themeConfig: { sidebar: { /guide/: [ install, config ], /blog/: [ 2025/02/hello, 2025/02/vuepress ] } }这样https://your-site.com/guide/install.html这个页面会使用/guide/下的侧边栏而https://your-site.com/blog/2025/02/hello.html会使用/blog/下的侧边栏。两个模块互不干扰各自维护自己的导航。需要说明的是对象键的路径必须以/开头目录形式的键建议以/结尾这样 VuePress 才能准确识别这是一个目录前缀而不是单个页面路径。1.3 路径匹配方案为什么比手动配置每个页面更合理有人可能想到另一个方案在每个文章的 frontmatter 里手动指定sidebar字段比如--- sidebar: - title: 分类A children: - / ---这种方式确实能给单个页面定制侧边栏但它的维护成本很高。假设你有五十篇文章每篇文章都要写一遍 sidebar 配置而且文章之间的侧边栏还要互相引用改一个标题就要改所有相关页面。这显然不是长期方案。路径前缀映射的价值就在于配置是集中式的所有页面自动归属到对应侧边栏。你只需要在config.js里定义好每个模块的侧边栏内容以后新写文章只要放到对应目录下侧边栏自动就会带上它不需要挨个改 frontmatter。2. 核心配置结构拆解2.1 sidebar 对象的基本写法VuePress 多个侧边栏的核心就是 sidebar 从数组变成一个对象。对象每个 key 是一个路径value 是对应侧边栏的数组配置。写个最基础的示例// .vuepress/config.js module.exports { title: 示例站点, themeConfig: { sidebar: { /guide/: [ , install, config ], /blog/: [ , 2025/02/first-post, 2025/02/vuepress-sidebar ], /: [ , about ] } } }这里需要解释几个容易糊涂的地方。children数组中的代表当前目录下的README.md。比如/guide/路径数组里写了对应的就是docs/guide/README.md在页面上渲染成/guide/。如果不写这个空字符串docs/guide/这个目录首页就不会出现在侧边栏里。数组里的install也不是随便写的它会被 VuePress 自动解析为docs/guide/install.md最终链接指向/guide/install.html。也就是说数组项相对于当前配置 key 的目录路径不需要写前导斜杠。第三个 key/是默认兜底配置。当某个页面没有匹配到更具体的路径前缀时就会使用/对应的侧边栏。在博客站点里我通常把首页、关于页这类全局页面放在这里。2.2 用分组对象让侧边栏更有层次上面那种平铺数组虽然已经按模块拆分了但每个模块内部如果内容多还是会出现一长串列表。VuePress 允许侧边栏数组的子项使用对象形式把侧边栏划分为多个可折叠的分组。/blog/: [ { title: 前端工程化, collapsable: true, children: [ [wit/01-vite, Vite 基础配置], wit/02-webpack, wit/03-rollup ] }, { title: 日常记录, collapsable: false, children: [ daily/backup, daily/server-troubleshooting ] } ]这个对象有四个常用字段title分组显示的名称会直接渲染在侧边栏上。collapsable是否允许折叠默认是true。个人经验是如果分组里页面不超过五个建议设成false让内容直接展开减少用户点击次数。children该分组下的页面路径数组。path可选给整个分组一个默认跳转链接。比如点击分组标题时跳到某个导读页面。还有一个很实用的写法在 children 数组里用二元数组自定义显示名称。比如children: [ [wit/01-vite, Vite 基础配置] ]这样侧边栏显示的是“Vite 基础配置”而实际链接指向wit/01-vite.html。如果你的 markdown 文件命名是日期加英文这样不利于阅读的形式或者文件内没有设置一级标题这个技巧就很有用。2.3 同一路径下支持通配符和嵌套键吗VuePress 1.x 的 sidebar 对象不只支持精确前缀匹配。键值支持类似正则的写法不过日常使用中大多数人用不到更常见的是嵌套键和通配需求。举例来说假设我的博客文章路径带日期docs/blog/2025/01/a.md docs/blog/2025/02/b.md如果不想维护/blog/2025/01/和/blog/2025/02/两个键更简单的做法是统一用/blog/作为键然后在 children 里写上相对路径2025/01/a和2025/02/b。这样也能实现多个侧边栏而且配置更集中。但如果你需要的是“博客文章所在的任意子路径都用同一个侧边栏”VuePress 1.x 的对象键还可以传入以/开头并以/结尾的字符串VuePress 会把它当作路径前缀匹配如果键以/开头但结尾不带/则是精确匹配单页面。平时不需要过度依赖正则先把目录结构规划好用目录前缀键就足够了。有一点要留心如果配置的键是/blog/而这个目录下还有子目录docs/blog/life/那么life中的页面也会自动匹配到/blog/这个侧边栏。如果你的本意是给life单独一个侧边栏就必须把/blog/life/这个更精确的键也加上。2.4 函数式 sidebar 的补充场景对象写法已经能覆盖绝大多数场景。但有一种情况它不太好处理某些页面希望根据当前页面路径动态生成侧边栏比如一个“标签页”或“分类页”它侧边栏的内容需要根据标签变化。函数式配置可以这样themeConfig: { sidebar: (pagePath) { if (pagePath.startsWith(/guide/)) { return [ [, 指南首页], install, config ] } if (pagePath.startsWith(/blog/)) { return [ { title: 博客索引, collapsable: false, children: [ 2025/01/hello, 2025/02/vuepress-sidebar ] } ] } return [] } }函数接收当前页面路径pagePath返回侧边栏配置。这种写法灵活性高但有个缺点它无法利用对象键的分目录自动补全逻辑所有 children 路径需要自己写完整。所以我建议优先用对象写法只有遇到需要根据运行时信息动态判断的场景再用函数。3. 实操过程从单侧边栏项目改成多个侧边栏3.1 第一步规划目录结构多个侧边栏不是为了配置而配置目录结构必须先理清。我当时的目录结构长这样docs/ ├── README.md ├── guide/ │ ├── README.md │ ├── install.md │ ├── quick-start.md │ └── advance/ │ ├── api.md │ └── plugin.md ├── blog/ │ ├── README.md │ ├── wit/ │ │ ├── 01-vite.md │ │ └── 02-webpack.md │ └── daily/ │ ├── backup.md │ └── server.md ├── about.md └── site/ └── index.md划分的原则很简单一个顶层目录尽量对应一个独立侧边栏。guide是技术文档块blog是博客文章块根目录/作为站点基础页面兜底。这样配置侧边栏时路径键和目录一一对应逻辑清晰。3.2 第二步编写多侧边栏配置在.vuepress/config.js里把 sidebar 改写成对象// .vuepress/config.js module.exports { title: 我的文档站, themeConfig: { sidebar: { /guide/: [ { title: 基础入门, collapsable: false, children: [ [, 指南总览], install, quick-start ] }, { title: 进阶主题, collapsable: true, children: [ advance/api, advance/plugin ] } ], /blog/: [ { title: 技术随笔, collapsable: false, children: [ [wit/01-vite, Vite 基础配置], [wit/02-webpack, Webpack 优化记录] ] }, { title: 运维日常, collapsable: true, children: [ daily/backup, daily/server ] } ], /: [ , about ], /site/: [ index ] } } }这里有三个细节值得展开。第一个细节/guide/下的分组中我写了[, 指南总览]。因为docs/guide/README.md这个页面默认从 markdown 的一级标题提取侧边栏文本但如果 README 里只写了很少的内容或者用了 frontmatter 中的 title显示效果可能不对。用二元数组手动指定显示文本就能保证侧边栏展示“指南总览”。第二个细节/blog/里我特意用二元数组给文件名“翻译”成中文标题。因为文件名叫01-vite.md如果不处理侧边栏就显示“01-vite”非常不友好。通过[wit/01-vite, Vite 基础配置]就能让它显示成可读性更高的标题。第三个细节/site/是一个只有一个页面的目录为什么也要单独配置因为这个页面我不想让它匹配到/的默认侧边栏所以给它配置了一个只包含自身的侧边栏。3.3 第三步验证效果与调整细节写完配置启动vuepress dev然后逐个访问不同路径检查侧边栏。检查的重点有几个访问/guide/install.html侧边栏只显示guide下的内容不出现博客文章。访问/blog/wit/01-vite.html侧边栏只显示blog下的分组。访问/about.html侧边栏显示默认的/配置。折叠和展开功能正常没有报错。如果某个页面侧边栏消失了最可能的原因就是路径前缀没有匹配上。比如页面路径是/blog/wit/01-vite.html但配置里只有/blog/wit/而没有/blog/那就匹配不到。所以我通常建议保留/兜底配置避免侧边栏完全空白。3.4 在实际场景中怎么处理“栏目首页”规划侧边栏时有一个常见疑问博客的文章列表页、分类页算不算一个独立“侧边栏”比如我的博客首页docs/blog/README.md它的侧边栏应该是什么我的做法是博客首页的侧边栏和博客文章保持同一个侧边栏配置这样用户从列表页进入单篇不会被突然变化的导航弄晕。如果你希望博客首页不显示侧边栏可以在docs/blog/README.md的 frontmatter 里加--- sidebar: false ---这会让 VuePress 在该页面隐藏侧边栏但保留导航栏。反过来某个页面需要完全自定义侧边栏也可以直接在 frontmatter 里写--- sidebar: - title: 自定义侧边栏 children: - / ---这种方式的优先级很高会覆盖全局 sidebar 配置。需要注意它不会自动获取目录下的所有页面children 里的路径都要完整写出来。因此我的经验是只用于少量特殊页面不要让所有页面都靠 frontmatter 维护侧边栏。4. 常见问题与排查技巧实录4.1 侧边栏整块消失这是改成多侧边栏之后最常遇到的问题。页面打开后侧边栏区域一片空白或者直接不显示。最常见原因是路径没匹配上。排查思路分三步查看页面的实际路径浏览器里地址栏显示/blog/wit/01-vite.html。检查 sidebar 对象里是否存在/blog/或/blog/wit/这样的键。确认数组里的子路径能正确解析到对应 md 文件。如果目录结构没问题再看一个容易忽略的点配置键必须以/开头和结尾。写成blog/、blog都是不行的。还有的同学会写成/blog, 这会被 VuePress 当作单页面路径来处理而不是目录前缀结果就是整个目录的页面都匹配不上。如果页面本身设置过sidebar: false或 frontmatter 中写错了 sidebar 类型也可能导致侧边栏不显示所以在排查时先删掉页面里的 frontmatter 试试。4.2 页面匹配到了错误的侧边栏假设我配置了两个键sidebar: { /blog/wit/: [01-vite, 02-webpack], /blog/: [README, daily/backup] }访问/blog/wit/01-vite.html时它同时满足/blog/wit/和/blog/两个前缀。按照 VuePress 1.x 的匹配逻辑VuePress 会优先使用匹配到的最具体、最长路径的配置所以实际会命中/blog/wit/。但如果你的 VuePress 版本或者配置顺序有差异也有可能命中更宽泛的配置。这里我给一个稳妥的建议把更具体的目录配置写在前面把更宽泛的目录配置写在后面。虽然 VuePress 大多数情况下能选中最长的匹配但手动排列顺序并不费事还能减少不确定性。更保险的写法是把父目录 children 里不要包含子目录的路径。比如/blog/的 children 只写blog/目录下的直接页面wit和daily子目录的页面交给各自的配置去管。我在某个项目里就遇到过这样的场景/blog/配置里有children: [daily/backup]同时/blog/daily/也是独立的一个键。结果访问backup.html时来回调整顺序才稳定下来。所以避免路径重叠才是根本对策。4.3 侧边栏里显示的标题是文件名很多第一次配置多侧边栏的朋友会发现侧边栏每一项显示的是文件名比如01-vite而不是文章里的标题。这是因为 VuePress 在字符串路径的形式下会尝试读取 markdown 文件内的标题如果文件内部没有一级标题或者标题设置得不规范它就会退回显示文件名。解决办法有两个确保每篇 markdown 文件顶部有一级标题# 页面标题。在 sidebar 配置中使用二元数组写死显示名称[wit/01-vite, Vite 基础配置]。我个人的习惯是对于博客文章这种文件名往往不规范的内容统一用二元数组指定显示名。这样即使以后改文件名也不会影响侧边栏显示效果。文档类页面则尽量在 md 里写好一级标题配置时保持字符串短写少维护一处。4.4 VuePress 2.x 的配置差异如果你用的是 VuePress 2.x上面的思路依然成立但配置入口有变化。2.x 依然在默认主题下使用sidebar配置但通常写在themeConfig中且一般通过vuepress/theme-default的sidebar字段传入结构基本一致。一个比较明显的差异是2.x 对 sidebar 类型的处理更严格函数式配置的返回值可能需要符合新的类型定义。如果你在升级项目后遇到类型报错可以先检查配置是否为合法对象/数组/函数再确认路径前导斜杠是否完整。由于 VuePress 2.x 的迭代比较快不同小版本之间可能有细微差别最靠谱的方式是直接查看当前项目安装的版本对应官方文档不要拿 1.x 的写法直接套到 2.x。4.5 自动标题侧边栏和多个侧边栏的取舍VuePress 默认主题支持sidebar: auto即根据当前页面的标题层级自动生成侧边栏。但要注意sidebar: auto在全局配置中只能作用于单个页面或整个站点如果你想每个模块都用自动标题侧边栏不能直接用对象写成sidebar: { /guide/: auto, /blog/: auto }在某些版本里这种写法并不能达到“多个自动侧边栏”的效果。原因很简单自动标题模式是从当前页面提取标题而多个侧边栏模式是从目录结构加载配置二者机制不同。如果你真的希望每个目录都自动生成标题侧边栏我见过有人用插件实现但插件生成的结构通常不够灵活。比如无法方便地自定义分组名称、调整排序。所以我最后的建议是文档站的侧边栏尽量手动配置内容多时用分组对象来组织自动标题模式更适合那种频繁变动的单页帮助文档不适合内容量大的多模块站点。4.6 一个留了很久的坑路径大小写与扩展名最后提醒一个特别容易犯的低级错误children 里的路径和文件名大小写不一致。Windows 本地开发时vuepress dev可能不报错因为文件系统大小写不敏感但部署到 Linux 服务器后侧边栏链接就 404。比如文件名是QuickStart.md配置里写成quick-start本地一切正常线上点击就跳转失败。所以写 sidebar 配置时路径尽量保持一致最好全部小写命名文件。另外children 中不要加.md或.html后缀VuePress 会自己处理。有一个排查技巧访问线上 404 页面时直接看浏览器里链接的路径然后对照自己的docs目录逐级检查。大多数时候就是大小写或者多写了一个目录层级的问题。5. 一些值得参考的扩展配置5.1 为分组设置默认跳转链接在侧边栏分组对象中加入path字段可以让用户点击组标题时跳转到指定页面{ title: 前端工程化, collapsable: true, path: /blog/wit/, children: [ 01-vite, 02-webpack ] }这个path不一定要是children中的某一项可以是独立的导读页或概览页。我在文档站的“进阶主题”分组里就加了path: /guide/advance/点分组标题直接进到进阶主题的概览页。需要注意加了path之后分组标题会默认带链接样式这是正常现象。如果不想让分组标题变成链接就不要设置path。5.2 配合导航栏实现模块切换多个侧边栏往往配合导航栏使用效果更好。在nav中设置对应链接用户点击导航按钮就能在不同模块间切换同时侧边栏也自动更新。themeConfig: { nav: [ { text: 指南, link: /guide/ }, { text: 博客, link: /blog/ }, { text: 关于, link: /about.html } ], sidebar: { // 多个侧边栏配置 } }这样整个站点的信息架构就变成顶部导航定位当前模块左侧侧边栏定位当前模块内部页面。用户的空间感会很清楚。5.3 首页隐藏侧边栏让全局配置更干净站点首页通常不适合显示侧边栏尤其是有大面积封面图时。在docs/README.md的 frontmatter 中加入--- home: true sidebar: false ---这样/下的侧边栏配置可以只保留 “关于”这一类全局页面首页保持干净。这也是我目前在实际项目中的做法根路径的/配置非常短主要做兜底真正的侧边栏内容都放在各个模块路径下。5.4 多侧边栏常见配置速查表为了便于快速对照我把常见需求对应的配置方式整理成一个表格场景配置位置方式所有页面共用侧边栏themeConfig.sidebar数组不同模块不同侧边栏themeConfig.sidebar对象键为路径前缀子路径内分组侧边栏数组内对象{title, children}自定义显示名称children 中二元数组[path, title]单页面隐藏侧边栏frontmattersidebar: false单页面独立侧边栏frontmattersidebar: [...]根据路径动态生成themeConfig.sidebar函数这个表格是我后来给团队里其他写文档的同事准备的他们对 VuePress 不熟但有这么一张表再配合示例基本十分钟就能上手。6. 最后说点实操体会多侧边栏这个功能本质上不是“多”字而是路径匹配。只要理解了 sidebar 对象中键和页面路径的对应关系剩下的就是目录规划和配置细节的问题。在我实际做过的几个 VuePress 站点里最稳定的结构就是一个顶层目录对应一个 sidebar 键每个键下的 children 尽量只写当前目录的直属文件子模块如果有独立需求就再加更具体的键然后永远保留一个/兜底。这套规则看似简单但能避免掉绝大多数侧边栏不显示、匹配错乱的问题。另外每次增加新模块时不要只往 sidebar 里塞路径顺便检查一下导航栏和首页入口是否同步更新。VuePress 的侧边栏不会自动扫描新增目录必须由你在配置里手动加一条所以养成“加目录就加配置”的习惯会省很多事。希望这篇内容能帮你顺利搞定多个侧边栏少走我之前走过的弯路。