构建共享 UI 组件库
在 Monorepo 架构中,共享 UI 组件库是保持应用一致性的关键。本文将介绍如何在 GoCode 中构建和使用 @repo/ui 组件库。
为什么需要共享组件库?
1. 保持视觉一致性
所有应用使用相同的组件,确保用户体验的一致性。
2. 减少重复代码
一次编写,多处使用,大幅减少代码重复。
3. 简化维护
修复 bug 或添加功能只需在一个地方进行。
4. 提高开发效率
开发者可以专注于业务逻辑,而不是重复造轮子。
技术栈
我们的 UI 组件库基于以下技术构建:
- React 19: 最新的 React 版本,支持 Server Components
- Tailwind CSS: 实用优先的 CSS 框架
- Shadcn UI: 高质量的 React 组件集合
- class-variance-authority: 类型安全的样式变体管理
- Radix UI: 无样式的可访问组件基础
组件示例
Button 组件
import { Button } from "@repo/ui";
export function Example() {
return (
<div className="flex gap-4">
<Button>默认按钮</Button>
<Button variant="outline">轮廓按钮</Button>
<Button variant="ghost">幽灵按钮</Button>
<Button size="lg">大按钮</Button>
</div>
);
}Card 组件
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
} from "@repo/ui";
export function Example() {
return (
<Card>
<CardHeader>
<CardTitle>卡片标题</CardTitle>
<CardDescription>卡片描述文本</CardDescription>
</CardHeader>
<CardContent>
<p>卡片内容区域</p>
</CardContent>
<CardFooter>
<Button>操作按钮</Button>
</CardFooter>
</Card>
);
}在不同框架中使用
Next.js (App Router)
在 Next.js 中直接导入即可:
import { Button, Card } from "@repo/ui";
export default function Page() {
return (
<main>
<Card>
<Button>点击我</Button>
</Card>
</main>
);
}Astro
在 Astro 中需要添加 client:load 指令:
---
import { Button, Card } from "@repo/ui";
---
<Card client:load>
<Button client:load>点击我</Button>
</Card>样式配置
Tailwind 配置
在应用的 tailwind.config.ts 中引入共享的 preset:
import type { Config } from "tailwindcss";
import sharedPreset from "@repo/ui/tailwind-preset";
const config: Config = {
content: [
"./src/**/*.{js,ts,jsx,tsx,astro}",
"../../packages/ui/src/**/*.{js,ts,jsx,tsx}",
],
presets: [sharedPreset],
};
export default config;CSS 导入
在应用的入口文件中导入样式:
import "@repo/ui/styles.css";最佳实践
1. 保持组件无状态
组件应该是纯展示性的,业务逻辑由应用层处理。
2. 使用 TypeScript
充分利用 TypeScript 的类型系统,提供更好的开发体验。
3. 文档化
为每个组件编写清晰的文档和示例。
4. 可访问性
确保所有组件符合 WCAG 标准,支持键盘导航和屏幕阅读器。
5. 性能优化
- 使用 React.memo 避免不必要的重渲染
- 合理使用 code splitting
- 优化 bundle 大小
总结
共享 UI 组件库是 Monorepo 架构的核心优势之一。通过合理的设计和实现,我们可以在保持灵活性的同时,大幅提高开发效率和代码质量。
下一篇文章将介绍如何在组件库中实现主题切换和暗色模式支持。
