首页
/ Storybook Angular 集成 Compodoc:angular.json Builder 配置完全指南

Storybook Angular 集成 Compodoc:angular.json Builder 配置完全指南

2026-09-07 09:17:40作者:蔡怀权

在 Storybook 的 Angular(Webpack)框架(@storybook/angular)中,Compodoc 承担着组件元数据提取的核心角色:只有把 angular.json 中的 Storybook Builder 正确配置为运行 Compodoc,Storybook 才能在渲染前生成 documentation.json 之类的文档元数据,进而为你的组件自动推断出 argTypes 与 Controls、生成 Autodocs 自动文档。本篇指南围绕官方配置片段 angular-project-compodoc-config.md 展开,逐字段拆解 storybookbuild-storybook 两个 Builder 的 Compodoc 配置,并结合仓库内的 Builder Schema 源码与配套 Snippet 说明底层默认值、compodocArgs 的参数语义、-d 输出目录在多项目 Workspace 下的陷阱,最终给出从安装、配置到验证的完整实操链路。读完你将能够独立把一个现有 Angular 工程接入 Compodoc,让 Controls、Args 表与自动文档开箱可用。

一、为什么 Angular 需要 Compodoc:先理解集成动机

在其他框架(如 React 依赖 react-docgen、Vue 依赖 vue-docgen-api)中,Storybook 各有对应的文档生成器。对使用 Webpack 构建的 @storybook/angular 框架而言,Storybook 选用的是 Compodoc——一个专为 Angular 应用设计的文档生成器。这一点在仓库文档 controls.mdx 的 Angular 分节中写得很明确:

Storybook uses Compodoc, a documentation generator for Angular applications that can extract the metadata of your components, including first-class support for Angular's inputs, outputs, properties, methods, and view/content child/children.

也就是说,Compodoc 能解析你的 TypeScript 源码与 JSDoc 注释,抽取 @Input()@Output()、属性、方法以及 @ViewChild / @ContentChild 等一等公民元数据。这些元数据最终决定了 Storybook 界面中:

  • Controls 面板:能展示并交互哪些参数(对应于组件的 @Inputs);
  • Args 表:自动生成的 argTypes 来自何处;
  • Autodocs 自动文档:文档内容由同一份元数据驱动。

正因如此,官方建议在 @Inputs@Outputs 上方添加解释性 JSDoc 注释——因为这两类元素正是用户会在 Storybook 里通过 Controls 交互的对象。

值得补充的是,本仓库同时维护着另一套基于 Vite 的 @storybook/angular-vite 框架,它默认从 TypeScript 源码直接推断元数据、无需额外工具(详见 controls.mdxangular-vite.mdx 中的说明)。而本文讨论的 Compodoc 配置针对的是经典的 @storybook/angular(Webpack) 框架。

二、配置前置:手动安装 Compodoc 依赖

如果你是通过 npx storybook@latest init 安装的 Storybook,初始化向导可以顺带完成 Compodoc 的自动设置;若 Storybook 已存在,则需要手动补齐依赖。仓库配套的安装片段 compodoc-install.md 给出了三种包管理器命令:

# npm
npm install @compodoc/compodoc --save-dev

# pnpm
pnpm add --save-dev @compodoc/compodoc

# yarn
yarn add --dev @compodoc/compodoc

安装完成后,Compodoc 以 @compodoc/compodoc 作为开发依赖存在,它不会再出现在你的 package.json scripts 中——因为在 @storybook/angular 里 Compodoc 已经内置进 Builder,无需手动调用 compodoc -p tsconfig.json -e json -d ./documentation 之类的旧式脚本(如果你之前手动执行过 compodoc,官方迁移指南建议删除相关 docs:json 脚本,详见 angular.mdx 的 FAQ 迁移章节)。

三、核心:angular.json 中的 Compodoc Builder 配置(完整示例)

下面是官方配置片段 angular-project-compodoc-config.md 的完整内容。它同时覆盖了开发服务器与静态构建两个 Builder,二者都需要声明 compodoc: true 与对应的 compodocArgs

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "your-project": {
      "projectType": "application",
      "schematics": {},
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "storybook": {
          "builder": "@storybook/angular:start-storybook",
          "options": {
            "configDir": ".storybook",
            "browserTarget": "your-project:build",
            "compodoc": true,
            "compodocArgs": [
              "-e",
              "json",
              "-d",
              ".", // Add this line to introspect the relevant files starting from the root directory of your project.
            ],
            "port": 6006,
          },
        },
        "build-storybook": {
          "builder": "@storybook/angular:build-storybook",
          "options": {
            "configDir": ".storybook",
            "browserTarget": "your-project:build",
            "compodoc": true,
            "compodocArgs": [
              "-e",
              "json",
              "-d",
              ".", // Add this line to introspect the relevant files starting from the root directory of your project.
            ],
            "outputDir": "storybook-static",
          },
        },
      },
    },
  },
}

3.1 storybook:开发模式 Builder

@storybook/angular:start-storybook 负责在本地以开发模式启动 Storybook,由 Angular CLI 通过 ng run <your-project>:storybook 触发。其关键选项:

选项 示例值 作用
builder @storybook/angular:start-storybook 选用 Angular Storybook 开发 Builder
configDir .storybook Storybook 配置目录(.storybook/main.tspreview.ts 等所在目录)
browserTarget your-project:build 指定复用的构建目标,以 project-name:builder:config 格式声明,Storybook 借此复用应用构建配置中的 stylesassets 等资源
compodoc true 显式开启“启动前先执行 Compodoc”
compodocArgs ["-e","json","-d","."] 传给 Compodoc 的参数(详见第四节)
port 6006 Storybook 开发服务器监听端口

3.2 build-storybook:静态构建 Builder

@storybook/angular:build-storybook 对应静态产物构建,由 ng run <your-project>:build-storybook 触发。除上述共有选项外,它还多了 outputDir(示例为 storybook-static),用于指定静态构建产物输出目录。根据 angular.mdx 的说明,在纯 Angular Workspace 配置下其默认输出位置是 dist/storybook/<your-project>

需要注意的是,两个 Builder 必须保持一致的 Compodoc 配置,否则会出现“开发模式有 Controls、构建产物却没有”这类不一致现象。

四、深入 compodocArgs:从 Builder Schema 看默认值与参数语义

如果你打开仓库中 Angular 框架的 start-schema.json,可以看到 compodoccompodocArgs 的官方 Schema 定义,它们揭示了配置背后的默认行为:

"compodoc": {
  "type": "boolean",
  "description": "Execute compodoc before.",
  "default": true
},
"compodocArgs": {
  "type": "array",
  "description": "Compodoc options : https://compodoc.app/guides/options.html. Options `-p` with tsconfig path and `-d` with workspace root is always given.",
  "default": ["-e", "json"],
  "items": { "type": "string" }
}

从这段 Schema 可以提炼出三条关键事实:

  1. compodoc 的默认值其实是 true:即使不在 angular.json 里显式书写 "compodoc": true,Builder 默认也会先执行 Compodoc。显式声明更多是一种“配置自文档化”的做法,便于后续维护者一眼看清行为。
  2. compodocArgs 的默认值是 ["-e", "json"]:即默认要求 Compodoc 以 JSON 格式输出文档。-e json 意为 --exportFormat json,这是 Storybook 读取元数据所必需的格式。
  3. -p-d 总会由 Builder 补全:Schema 明确写道 “Options -p with tsconfig path and -d with workspace root is always given”——也就是 Builder 会自动附加 -p(指向 tsconfig 路径)与 -d(指向 workspace root),你无需(也不必)在 compodocArgs 中重复提供 -p

4.1 那为什么示例中还要加 "-d", "."

这看起来与“-d 总会自动给出”矛盾,实则不然。关键在于:Schema 中“自动给出”的 -d 指向的是 Angular Workspace 根目录,而 Compodoc 生成的 documentation.json 需要被 .storybook/preview.ts 通过相对导入读取。在多项目 Workspace(即 angular.jsonnewProjectRoot 下存在多个 project)场景里,Workspace 根目录 ≠ 某个 Angular 项目根目录,默认写入位置可能与你预期的导入路径不符。

因此官方在示例中显式追加 "-d", ".",并加了注释:

Add this line to introspect the relevant files starting from the root directory of your project.

即把文档输出目录固定为当前项目根目录(注意:是该项目目录本身,而非整个 Workspace 根目录)。angular.json 中该 project 的 root 字段决定了 ng run 执行时的相对基准——在示例配置里 "root": "" 表示项目即位于仓库根。这个细节在 angular.mdx 的注释里有完全一致的表述:-d 的取值“通常是你的 Angular 项目根目录,而不一定是你的 Angular Workspace 根目录!”

4.2 输出文件与导入路径的对应关系

-d . 指向项目根时,生成的元数据文件即为项目根下的 documentation.json。相应的,.storybook/preview.ts 中需要以 ../documentation.json 的方式导入它(见下一节)。这正是 -d 值与 preview 导入路径必须手动对齐的原因。

五、收尾接线:在 preview.ts 中把元数据喂给 Storybook

angular.json 只解决了“生成元数据”这一步,要让 Storybook 真正消费这些元数据,还必须修改 .storybook/preview.ts。这一步在配置片段所属的官方流程中紧随其后,配套的 preview 配置片段见 storybook-preview-compodoc-config.md

import type { Preview } from '@storybook/angular';
import { setCompodocJson } from '@storybook/addon-docs/angular';

import docJson from '../documentation.json'; // The path to your generated json file from Compodoc contains all your documentation information.

setCompodocJson(docJson);

const preview: Preview = {
  parameters: {
    actions: { argTypesRegex: '^on[A-Z].*' },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
  },
};

export default preview;

这里发生的关键调用是 setCompodocJson(docJson),它来自 @storybook/addon-docs/angular(即 code/addons/docs 下的 Angular 入口)。该函数把 Compodoc 产出的元数据注册进 Storybook 的 Docs/Controls 管线,之后 Storybook 才能基于 @Inputs@Outputs 等元数据为组件自动生成 argTypes

仓库还同时维护了 CSF3 与 CSF Next 两种写法下同一配置的变体片段 angular-add-compodoc.md,核心三行完全一致:

import { setCompodocJson } from '@storybook/addon-docs/angular';
import docJson from '../documentation.json';
setCompodocJson(docJson);

区别仅在 preview 对象的声明方式上:CSF 3 使用 const preview: Preview = {...} 配合 export default preview,而 CSF Next 使用 definePreview({...})。无论哪种写法,setCompodocJson 都是让 Storybook 认识 Compodoc 元数据的唯一入口。

六、端到端效果:Controls 如何因 Compodoc 而自动生成

完成上述两步配置后,你便获得了官方文档中描述的完整能力链路(参见 controls.mdx 的 Angular 章节):当你在 story 文件的 meta 中设置了 component 注解时,Storybook 会使用 Compodoc 提取的组件定义自动推断 argTypes 并生成对应的 Controls。也就是说,写完如下形式的 stories 后,Controls 面板就“凭空”出现了:

import { Meta, StoryObj } from '@storybook/angular';
import { YourComponent } from './your.component';

const meta: Meta<YourComponent> = {
  component: YourComponent, // 基于此注解推断 controls 与 argTypes
};
export default meta;
type Story = StoryObj<YourComponent>;

export const Base: Story = {};

为了获得更好的推断效果,官方强烈建议在 @Inputs / @Outputs 上书写描述性 JSDoc——这些注释会被 Compodoc 收集,最终呈现在 Args 表与 Autodocs 中。若未启用 Compodoc 或元数据缺失,Angular(Webpack)框架下将退回手动定义 argTypes 的老路,这正是该集成配置价值所在。

七、多项目 Workspace 与常见误区

结合 angular.mdx 的迁移与 FAQ 章节,在多项目场景下需要额外注意:

  • 每个项目要有独立的 .storybook 目录,放置在对应项目的根目录;并分别在其 angular.jsonarchitect 下配置本文所述的 builder 选项。
  • -d . 的相对基准随 ng run <project> 切换:由于每个 project 的 root 可能不同,务必为每个项目核对 compodocArgs-d 的取值与对应 .storybook/preview.ts 的导入路径是否指向同一个 documentation.json
  • 输出目录与导入路径须成对维护:若将 -d 改为 ./documentation 之类的子目录,则 preview.ts 的导入路径也要同步改为 ../documentation/documentation.json
  • 若此前通过 npm run docs:json 之类的脚本在启动 Storybook 前手动调用 compodoc,迁移到 Builder 后可删除该脚本——@storybook/angular 已把 compodoc 执行内置进 builder(参考 angular.mdx 的 diff 示例)。

八、验证配置是否生效

配置完成后,按如下顺序自检:

  1. 启动开发模式:在项目根目录执行 ng run <your-project>:storybook。观察终端输出中是否出现 Compodoc 执行记录,且项目根目录生成 documentation.json
  2. 检查 preview 加载:确认 .storybook/preview.ts 中的 import docJson from '../documentation.json' 指向真实存在的文件(可用相对路径对比 -d 的输出位置)。
  3. 验证 UI 表现:打开某个为组件设置了 component 注解的 story,若 Args 表中自动列出了 @Inputs / @Outputs,且 Controls 面板能交互调节参数,则说明元数据链路已打通。
  4. 验证静态构建:执行 ng run <your-project>:build-storybook,在 outputDirstorybook-static 或默认 dist/storybook/<your-project>)中找到产物并本地预览,确保构建产物同样包含 Controls 与文档。

只要 Builder 配置(compodoc + compodocArgs)与 preview 接线(setCompodocJson)两侧一致,Compodoc 驱动的自动文档体验便会在 Angular 工程中稳定生效——这正是从一篇 angular.json 片段出发、读懂整条 Angular 文档生成链路的核心收益。

登录后查看全文
热门项目推荐
相关项目推荐