基于Storybook与AI的组件文档自动生成流水线
在前端组件库和设计系统的长期维护中,编写 Storybook Stories 和 API 文档往往被视为一件“重要但不紧急、极度耗费精力”的差事。
很多团队的组件库往往是代码先写完了,但文档永远停留在半年前的版本:
- Props 参数说明缺失,新人开发者只能翻源码看 TypeScript 接口;
- 缺乏可交互的 Controls 用例演示;
- 边缘状态(如加载中 Loading、禁用 Disabled、错误报错 Error、超长文本截断)没有独立的 Story 覆盖。
为了彻底实现“代码写完即文档就绪”,我们设计了一套结合 TypeScript AST 解析与大模型生成能力的 Storybook 自动化流水线,能够在 10 秒内为任意 React/Vue 组件输出规范的*.stories.tsx文件与 Markdown 使用说明。
自动化流水线架构设计
整个生成流水线分为三步:
[ 源码组件 Button.tsx ] │ ▼ (步骤 1: ts-morph 静态 AST 提取) ┌─────────────────────────────────────────────────────────────┐ │ 提取组件名称、Props 接口类型、JSDoc 注释、默认值与导入路径 │ └──────────────────────────────┬──────────────────────────────┘ │ ▼ (步骤 2: 注入结构化 Prompt) ┌─────────────────────────────────────────────────────────────┐ │ LLM 针对性生成 Default / Variants / Edge Cases 的 Story 代码│ └──────────────────────────────┬──────────────────────────────┘ │ ▼ (步骤 3: 格式化与落盘) [ 生成 Button.stories.tsx 并自动通过 Prettier 校验 ]核心实现一:基于 AST 提取组件元数据
使用ts-morph快速提取组件的接口声明,避免将上千行无关的内部实现细节塞给大模型,节省 Token 并提高生成精准度:
// scripts/extract-component-meta.ts import { Project } from 'ts-morph'; export interface ComponentMetadata { name: string; props: Array<{ name: string; type: string; description: string; required: boolean; defaultValue?: string; }>; } export function extractComponentMeta(filePath: string): ComponentMetadata { const project = new Project(); const sourceFile = project.addSourceFileAtPath(filePath); // 查找导出的组件函数 const componentDeclaration = sourceFile.getFunction(f => f.isExported()) || sourceFile.getVariableDeclaration(v => v.isExported()); const name = componentDeclaration?.getName() || 'UnknownComponent'; // 查找 Props 接口 const propsInterface = sourceFile.getInterface(i => i.getName().includes('Props')); const props: ComponentMetadata['props'] = []; if (propsInterface) { for (const prop of propsInterface.getProperties()) { props.push({ name: prop.getName(), type: prop.getType().getText(), description: prop.getJsDocs().map(d => d.getCommentText()).join(' ') || '', required: !prop.hasQuestionToken() }); } } return { name, props }; }核心实现二:生成生产级 Storybook 代码
将提取出的元数据交给大模型,按照 Component Story Format (CSF 3) 规范生成标准 Stories:
// 生成的 Button.stories.tsx 示例 import type { Meta, StoryObj } from '@storybook/react'; import { Button } from './Button'; const meta: Meta<typeof Button> = { title: 'Components/Button', component: Button, tags: ['autodocs'], argTypes: { variant: { control: 'select', options: ['primary', 'secondary', 'danger', 'outline'], description: '按钮的主题样式' }, size: { control: 'radio', options: ['sm', 'md', 'lg'], description: '按钮尺寸规格' }, isLoading: { control: 'boolean', description: '是否处于加载中状态' } } }; export default meta; type Story = StoryObj<typeof Button>; // 1. 默认基础故事 export const Default: Story = { args: { children: '确认提交', variant: 'primary', size: 'md' } }; // 2. 加载中状态 export const LoadingState: Story = { args: { children: '正在生成中...', isLoading: true, variant: 'primary' } }; // 3. 危险操作状态 export const DangerVariant: Story = { args: { children: '删除记录', variant: 'danger' } };实践收益
- 组件库文档覆盖率从 30% 跃升至 100%:每次新增或重构组件时,通过一行命令
pnpm gen:story src/components/Card.tsx即可瞬间生成完备文档; - 多态与边界用例一目了然:AI 会自动根据 Props 类型穷举出所有的 Variant 与极限量测(如超长文本、空状态、禁用态),极大减轻了前端与 UI 设计师的走查成本。