组件生成
从模板脚手架新 UI 组件,带正确结构、测试和 Storybook story。
为什么
设计系统里每组件应有相同结构:props 接口、forwardRef、含所有变体的 Storybook story 和单元测试。手工为每新组件创建这 4 文件浪费 15 分钟且引入不一致——一些组件有测试一些没有,一些用 forwardRef 一些忘。生成器(plop、hygen 或自定义脚本)5 秒从模板产 4 文件,每次强制相同结构。这是设计系统扩到 100+ 组件不变维护噩梦的方式:结构统一,新组件入职零努力。
何时使用
有 ≥10 组件或设计系统时。搭 plop 约 1 小时。一次性组件可跳过。
如何做
1. 装 plop 创建含组件生成器的 plopfile - 提示:组件名、目录(atoms/molecules/organisms)、hasVariants - 模板:Component.tsx、Component.test.tsx、Component.stories.tsx、index.ts 2. 模板 Component.tsx 用标准结构 - React.forwardRef、类型化 props 接口、cn() 合并 className - 命名 + 默认导出;含 DevTools displayName 3. 模板 Storybook story 至少含:default、with className、disabled - 用 args 组合让变体继承基础 args - 加 docsOnly story 供文档化不渲染 4. 模板测试含 render + 快照 + 行为测试 - render(<Component />) 不应抛 - 测关键交互(click、input)——非仅渲染 5. 接入 package.json:"gen:component": "plop component" - 跑它,答 3 提示,得 4 文件首次即过 lint+test
示例
// plopfile.ts
export default function (plop) {
plop.setGenerator("component", {
prompts: [
{ type: "input", name: "name", message: "组件名(PascalCase)" },
{ type: "list", name: "level", choices: ["atoms", "molecules", "organisms"] },
],
actions: [
{ type: "add", path: "src/components/{{level}}/{{name}}/{{name}}.tsx", templateFile: "templates/Component.tsx.hbs" },
{ type: "add", path: "src/components/{{level}}/{{name}}/{{name}}.test.tsx", templateFile: "templates/Component.test.tsx.hbs" },
{ type: "add", path: "src/components/{{level}}/{{name}}/{{name}}.stories.tsx", templateFile: "templates/Component.stories.tsx.hbs" },
],
});
}
// templates/Component.tsx.hbs
import { forwardRef } from "react";
export interface {{name}}Props { className?: string; }
export const {{name}} = forwardRef<HTMLDivElement, {{name}}Props>(function {{name}}({ className }, ref) {
return <div ref={ref} className={className} />;
});
{{name}}.displayName = "{{name}}";常见问题
- ⚠模板与实际项目约定漂移,生成代码每次要手修。
- ⚠只生成 .tsx 无测试或 story,组件存在但无文档无测试。
- ⚠不处理复合组件(Select + Option)一个生成器应产多相关文件。
- ⚠生成后忘更新桶导出(index.ts),组件不可导入。
最佳实践
- ✓模板放仓库像其他代码一样评审变更——它们生成代码,高杠杆。
- ✓加生成后步骤对新文件跑 lint+test,不过则失败——抓模板漂移。
- ✓一个生成器用 'compound' 提示支持简单和复合组件,加子文件。
- ✓生成 Storybook story 启 autodocs,组件第一天即文档化。