隐藏页面:不进导航栏的文档
本页说明本站的一个实际做法:为什么 /docs/ 那页既不在导航栏、也不在侧边栏里,却仍能正常打开。
顺便,本页自己就是这种做法的一个样本——它同样不在任何侧边栏里,只能靠直接链接进入。
一句话原理
Docusaurus 的侧边栏不是"自动列出全部文档",而是"只列出被某个 sidebar 收录的文档"。
导航栏里的 docSidebar 栏位又只是"指向某个 sidebar 的入口"。
不被任何 sidebar 收录 = 不出现在侧边栏,也就不会出现在导航栏;但页面照常生成,输入 URL 就能访问。
/docs/ 就是这种情况。
它是怎么被"藏"起来的
需要三件事同时成立,少一件它就会露出来:
| # | 条件 | 本项目的具体位置 |
|---|---|---|
| 1 | 文档文件不在任何 autogenerated 目录的覆盖范围内 | docs/overview.mdx 直接放在 docs/ 根目录;而两个 sidebar 只 autogenerate in-progress/ 与 completed/ |
| 2 | 没有任何 sidebar 显式列举它 | sidebars.js 里只写了「施工中」「已完成」两个分类 |
| 3 | 导航栏里没有指向它的入口 | docusaurus.config.js 的 navbar.items 只有 🛠施工中🛠、🛠已完成🛠、🗨公告栏🗨 |
结果是:页面上任何可点的链接都到不了它,但 docs 插件依然会为每一个 .mdx 生成路由。这是"隐藏",不是"删除"。
为什么它看起来像一张独立落地页
还有两个附带的副作用,正好解释了它的观感:
- 这一页连左侧那一列都不渲染。
主题的文档布局里写的是
{sidebar && <DocRootLayoutSidebar />}(见@docusaurus/theme-classic/lib/theme/DocRoot/Layout/index.js)。 当文档不属于任何 sidebar 时,它的sidebar是null,整个侧边栏分支被跳过,正文占满宽度。 实测构建产物里,<aside>那层侧边栏容器根本没有输出,侧边栏菜单的ul也不存在。 - URL 完全由 frontmatter 的
slug决定。 规则是/<routeBasePath>/<slug>;本项目routeBasePath是docs,所以slug: /得到/docs/,slug: /hidden-pages得到/docs/hidden-pages。
新增一个这样的文档
第 1 步:选位置(唯一容易做错的一步)
必须放在没有被任何 autogenerated 覆盖的目录里:
- ✅
docs/根目录,或另建一个如docs/guides/的目录 - ❌ 不要放进
docs/in-progress/或docs/completed/—— 那两个目录被 autogenerate 覆盖,放进去会立刻出现在对应栏位的侧边栏里
docs/
├── in-progress/ ← 被 inProgressSidebar autogenerate,放进去就进侧边栏
│ ├── 01-changelog.mdx
│ └── 02-roadmap.mdx
├── completed/ ← 被 completedSidebar autogenerate,同理
│ ├── 01-about.mdx
│ └── 02-copyright.mdx
├── overview.mdx ← 隐藏页:不在任何 autogenerated 目录内
├── hidden-pages.mdx ← 隐藏页:本页
└── guides/ ← 新建的目录同样不会被收录
└── any-hidden.mdx
第 2 步:写 frontmatter 与正文
---
slug: /hidden-pages # 决定 URL:本页即 /docs/hidden-pages
title: 页面标题 # 浏览器标签与页面大标题
description: 一句话简介 # 写进 <meta name="description">
---
正文……
文件名只影响文档 id,URL 由 slug 说了算。不加 slug 时才会退回按文件路径生成。
第 3 步(可选):加 unlisted: true 彻底隐藏
不加也能达到"不在导航栏"的效果。加上之后,官方文档(plugin-content-docs → Markdown front matter)承诺的行为是:
Unlisted documents will be available in both development and production. They will be "hidden" in production, not indexed, excluded from sitemaps, and can only be accessed by users having a direct link.
落到实际产物上会多出三件事:
- 页面
<head>里注入<meta name="robots" content="noindex, nofollow">; - 不进
sitemap.xml,也不进搜索索引; - 正文顶部自动多出一条
caution横幅:标题「未列出页」,文案「此页面未列出。搜索引擎不会对其索引,只有拥有直接链接的用户才能访问。」
unlisted 的差别同样不在导航里,但会被 sitemap 收录、也能被搜索引擎索引。
实测当前 /docs/ 就在 build/sitemap.xml 里,且整页没有任何 robots meta。
所以"藏"到什么程度,取决于你要不要连搜索引擎也找不到它。
第 4 步(可选):给它一个入口
"不进导航栏"不等于"不能有入口"。三种常见做法:
-
从别的文档里写普通链接:
[隐藏页面](/docs/hidden-pages) -
导航栏加一个自定义项(
navbar.items里的to型条目,完全不经过任何 sidebar):{to: '/docs/hidden-pages', label: '🗂内部说明🗂', position: 'left'}, -
只给自己留门:链接只写在某一篇文档内,导航栏一个都不放。
本站配置了 onBrokenLinks: 'throw'。只要写了链接,路径就必须真实存在(含 slug 是否正确),否则构建直接失败。
补充:想要侧边栏,但不想被收录
如果希望这一页打开时仍显示左侧边栏(方便跳回其它文档),却不想它出现在侧边栏列表里,用 frontmatter:
displayed_sidebar: completedSidebar
displayed_sidebar 只决定"这一页显示哪个 sidebar",不会把该页加进那个 sidebar。它是"隐藏页"与"可导航"之间很好的折中。
三种"藏"的力度对比
| 做法 | 侧边栏 | 导航栏 | sitemap / 索引 | 打开方式 | 适用场景 |
|---|---|---|---|---|---|
只靠"不被 sidebar 收录"(本站 /docs/ 现状) | 不出现 | 无入口 | 仍会收录 | 直链 | 低调,但不介意被搜到 |
再加 unlisted: true | 不出现 | 无入口 | 不收录 | 直链 | 纯内部页、不想曝光 |
draft: true | 不出现 | 无入口 | 不进生产产物 | 仅 npm start 时可见 | 没写完,不想上线 |
本站目前有哪些这类页面
| 页面 | URL | 入口 |
|---|---|---|
| 编译局总览 | /docs/ | 首页「一起阅读吧!」按钮 |
| 本页(做法说明) | /docs/hidden-pages | /docs/ 总览页底部的链接 |
脚手架残留:intro、tutorial-basics/*、tutorial-extras/* | /docs/intro 等 | 无入口 |
最后一行是同一个原理的另一种用法:文件保留、路由照常可访问,但 sidebars.js 刻意不列举它们,于是从侧边栏里"退出"了(Docusaurus 没有目录级的排除配置,显式枚举是唯一干净的做法)。
常见坑
- 位置放错:只要文件落进被
autogenerated覆盖的目录,它就自动进侧边栏,隐藏立刻失效。 slug冲突:两篇文档写同一个slug会构建报错。- 文件名前缀
NN-:会被 Docusaurus 剥掉、不进 URL,只用来控制排序。别靠文件名猜 URL。 - 想在
/docs/之外开页面:隐藏页做不到——slug始终挂在routeBasePath之下。 要顶级路由(例如/about)应把 mdx 放到src/pages/(如src/pages/about.mdx→/about), 代价是没有 docs 的上下篇、侧边栏、版本这些能力。
怎么自查
改完之后跑一次构建,再直接读产物即可验收:
npm run build
然后在产物里确认三件事:
- 路由生成了:
build/docs/<你的 slug>/index.html存在。 - 没渲染侧边栏:在该文件的 HTML 里搜
<aside class="theme-doc-sidebar-container,应为 0 处命中。 (要点是必须带上尖括号:正文里的<会被转义成<,所以"尖括号 + 标签名"这种写法永远不会被自己的正文命中。 反过来,如果只搜不含尖括号的裸类名词,这类词在正文里是原样输出的,说明文字本身就会被算进去,得到假阳性。) - 没有导航入口:在首页
build/index.html里搜你的 slug,它不应出现在导航栏链接中(导航条目的类名是navbar__link);如果它出现在正文链接里,那只是你手动加的入口,不影响"隐藏"。