Storybook `docs.defaultName` 配置详解:为自动生成的文档页自定义侧边栏名称
本文围绕 Storybook 主配置(.storybook/main.js|ts|cjs)中的 docs.defaultName 选项展开,说明它如何决定自动生成的文档页(Autodocs 与 MDX 文档条目)在侧边栏中显示的名称。你将看到完整的 JS / TS / CSF Next(defineMain)配置示例、默认值行为、底层索引生成链路与自动命名规则,以及命名冲突时的报错含义与规避方法。
这一配置项解决什么问题
Storybook 会根据你的故事文件自动生成文档页面。当某个 CSF 文件中的故事带有 autodocs 标签(或在 preview 中全局开启)时,Storybook 会为该组件生成一个文档页,并把它放在组件树的根部;这个页面在侧边栏中的默认名称是 Docs。docs.defaultName 就是用来覆盖这个默认名称的入口:
// 类型形态(摘自 docs/api/main-config/main-config-docs.mdx)
{
defaultName?: string;
docsMode?: boolean;
}
它属于 docs 配置(即“配置自动生成文档”的命名空间),同级的 docsMode 用来只显示文档页。而“自动生成文档”功能本身的启用与机制,参见 Autodocs 章节。defaultName 在该文档的功能对照表中被描述为:重命名自动生成的文档页面,默认值为 docs: { defaultName: 'Docs' }。
如何在 main 配置中设置
在 .storybook/main.js 或 .storybook/main.ts 中,为顶层 docs 字段传入 defaultName 即可。下面是与官方代码片段一致的完整写法。
CSF 3 + JavaScript(renderer 通用)
export default {
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
docs: {
defaultName: 'Documentation',
},
};
CSF 3 + TypeScript(renderer 通用)
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
docs: {
defaultName: 'Documentation',
},
};
export default config;
CSF Next(🧪 实验性 API)+ TypeScript:
// Replace your-framework with the framework you are using (e.g., react-vite, nextjs, nextjs-vite)
import { defineMain } from '@storybook/your-framework/node';
export default defineMain({
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
docs: {
defaultName: 'Documentation',
},
});
采用 CSF Next 写法时,defineMain 的导入来源随框架而不同,其余配置结构完全一致:
| renderer | defineMain 导入 |
|---|---|
| React(react-vite / nextjs / nextjs-vite) | import { defineMain } from '@storybook/your-framework/node' |
| Vue 3 | import { defineMain } from '@storybook/vue3-vite/node' |
| Angular | import { defineMain } from '@storybook/angular/node' |
| Web Components | import { defineMain } from '@storybook/web-components-vite/node' |
例如 Vue 3 项目对应为:
import { defineMain } from '@storybook/vue3-vite/node';
export default defineMain({
framework: '@storybook/vue3-vite',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
docs: {
defaultName: 'Documentation',
},
});
Angular、Web Components 仅需替换 import 与 framework 值即可。设置后,重新启动 Storybook,所有自动生成的文档页在侧边栏中都会以 Documentation 命名。
类型定义与默认值出处
docs.defaultName 的语义在类型层已被明确注释,见 core-common.ts:
export type DocsOptions = {
/** What should we call the generated docs entries? */
defaultName?: string;
/** Only show doc entries in the side bar (usually set with the `--docs` CLI flag) */
docsMode?: boolean;
};
其中 “generated docs entries” 即索引(story index)中那些 type: 'docs' 的条目——既包含由 CSF + autodocs 标签自动生成的组件文档页,也包含 MDX 文档条目。当未配置时,代码中通过空值合并运算符回退到字符串 'Docs'(即 API 文档标注的 Default: 'Docs')。
底层实现:名称如何进入文档索引
文档页名称的最终落地发生在核心服务端的索引生成器 StoryIndexGenerator.ts 中。它主要在三条路径读取该选项:
1. 为带 autodocs 标签的 CSF 生成“附加式”文档条目
在 StoryIndexGenerator.ts 中,当一个 CSF 文件至少包含一个带 autodocs 标签的故事时,会生成一条 type: 'docs' 的文档条目:
const createDocEntry = hasAutodocsTag && !!this.options.docs;
if (createDocEntry && this.options.build?.test?.disableAutoDocs !== true) {
const docsName = this.options.docs?.defaultName ?? 'Docs';
const name = docsName;
const { metaId } = indexInputs[0];
const entry = storyEntries[0];
const id = toId(metaId ?? entry.title, name);
...
可见 name 直接取 docs.defaultName(缺省为 'Docs'),并且该名称参与了 id 的生成(toId(title, name))。
2. 为 MDX 文档文件生成条目
在 extractDocs 中,MDX 条目的名称优先级是:MDX 中显式声明的名称 → 附加式 MDX(<Meta of={} />)的自动命名 → 回退到 defaultName:
const defaultName = this.options.docs?.defaultName ?? 'Docs';
const name =
result.name ||
(csfEntry ? autoName(importPath, csfEntry.importPath, defaultName) : defaultName);
const id = toId(csfEntry?.extra.metaId || result.id || title, name);
其中 result.name 来自 MDX 内 <Meta name="..."> 的显式指定。
3. 文档页与故事同名时的冲突检测
在 chooseDuplicate(StoryIndexGenerator.ts)中,当存在与默认文档页同名的故事条目时,索引会报错并给出修复建议,错误信息里同样读取 defaultName:
const docsName = this.options.docs?.defaultName ?? 'Docs';
if (betterEntry.name === docsName) {
throw new IndexingError(
`You have a story for ${betterEntry.title} with the same name as your default docs entry name (${betterEntry.name}), so the docs page is being dropped. Consider changing the story name.`,
...
);
}
这三条路径共同说明了一个事实:defaultName 不只是一段显示文本,它还会影响文档条目的 ID 与命名冲突判定。例如默认配置下,测试快照中的文档条目 ID 形如 componentreference--docs、tags--docs;一旦你把它改成 Documentation,由 toId(title, name) 派生的文档条目 ID 后缀也会随之变化,指向文档页的链接(permalink)同样会变化。这一点从实现可以推断,升级或改配置时需要注意链接的稳定性。
自动命名规则:什么时候真的会用到 defaultName
并非所有 MDX 文档页都会直接使用 defaultName。对通过 <Meta of={ComponentStories} /> 关联到某个 CSF 的“附加式 MDX”,命名规则集中在 autoName.ts:
- 若 MDX 文件与 CSF 文件的基础名相同(例如
Button.mdx与Button.stories.jsx都基于Button),则使用defaultName; - 否则使用 MDX 文件去掉扩展名后的文件名。
export function autoName(mdxImportPath: Path, csfImportPath: Path, defaultName: string) {
const mdxBasename = basename(mdxImportPath);
const csfBasename = basename(csfImportPath);
const [mdxFilename] = mdxBasename.split('.');
const [csfFilename] = csfBasename.split('.');
if (mdxFilename === csfFilename) {
return defaultName;
}
return mdxFilename;
}
典型行为:
Button.mdx+Button.stories.jsx→ 使用docs.defaultName(如Documentation);ButtonMeta.mdx+Button.stories.jsx→ 使用ButtonMeta;- 独立的(非附加)MDX 且未显式命名 → 回退到
docs.defaultName。
对自动生成文档页(Autodocs)本身,defaultName 则直接作为名称使用。因此,该项目中最常见、也最立竿见影的用法,就是把 Autodocs 页面从默认的 Docs 统一重命名为团队约定名称(如 Documentation、API、Info 等)。
索引测试中的验证
以上行为都有测试用例支撑,见 StoryIndexGenerator.test.ts:
- “Allows you to override default name for docs files”用例(约 第 1738 行)将
defaultName设为'Info'后断言索引快照; - “errors when a story has the default docs name”用例(约 第 2153 行)将
defaultName设为'Story One',验证与故事同名时索引报错; index-json.test.ts、__tests__/index-extraction.test.ts中也以docs: { defaultName: 'docs' }作为常规测试配置。
如果你改动该选项后 Storybook 无法正常生成索引,可以参考这些用例的断言来核对名称与 ID 的预期形态。
与 docsMode 的关系
defaultName 与 docsMode 同属 DocsOptions,且都写在 .storybook/main.js 的同一个 docs 块里,示例见 docs-mode 代码片段:
export default {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
docs: {
docsMode: true,
},
};
二者分工不同:
| 选项 | 类型 | 默认值 | 作用 |
|---|---|---|---|
defaultName |
string |
'Docs' |
自动生成文档页在侧边栏中的名称 |
docsMode |
boolean |
false |
侧边栏只展示文档页(通常由 --docs CLI 标志位开启) |
也就是说:defaultName 解决“文档页叫什么”,docsMode 解决“是否只保留文档视图”。日常把它俩放在同一个 docs 配置块即可。
使用建议
- 先在
.storybook/main.js|ts|cjs中找到或新建顶层docs块,再写入defaultName,无需改动任何故事文件或 MDX; - 若团队希望文档入口不叫
Docs而叫别的名字,这是全局生效的最小改动;个别页面若想单独命名,可在对应 MDX 中使用<Meta name="...">,其优先级高于自动命名; - 注意避免与
defaultName同名的故事存在(例如不要新建一个名为Docs的故事),否则 Storybook 会以索引错误提示该文档页会被丢弃,需要重命名故事或调整默认名; - 修改该配置会同步改变文档条目的名称与 ID,若文档页链接已被外部引用,需评估影响后再改。
更完整的功能背景可继续阅读 Autodocs 文档、docs 配置 API,并对照 官方代码片段 验证各 renderer 下的写法差异。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0630
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00