挑戰: 構建跨平台 UI 組件庫,前後端完美對齊
解決方案: Schema Registry + JSON-as-Object Pattern
- 組件數量: 50+ 組件
- 平台: Web (React) + Backend (Rust) + Mobile (React Native)
- 團隊: 前端 5 人 + 後端 3 人 + 設計 2 人
- 開發週期: 3 個月 (vs 傳統方式 8-12 個月)
需求: Web、Mobile、後台管理系統使用相同組件庫
- 相同的 Props 定義
- 相同的驗證邏輯
- 相同的設計規範
設計團隊要求:
- 顏色只能用設計系統定義的 8 種
- 尺寸只能是 sm/md/lg/xl
- 間距必須是 4 的倍數
產品需求: 用戶可以通過配置生成自定義 Dashboard
- 拖拽組件
- 配置 Props
- 實時預覽
- 保存配置到後端
schemas/
├── design-system/ # 設計系統規範
│ ├── colors.schema.json # 8 種顏色
│ ├── sizes.schema.json # 4 種尺寸
│ └── spacing.schema.json # 間距規範
│
├── components/ # 50+ 組件
│ ├── Button.schema.json
│ ├── Input.schema.json
│ ├── Modal.schema.json
│ ├── Table.schema.json
│ └── Chart.schema.json
│
├── compositions/ # 組合組件
│ ├── LoginForm.schema.json
│ ├── Dashboard.schema.json
│ └── DataTable.schema.json
│
└── layouts/ # 佈局組件
├── Grid.schema.json
└── Flex.schema.json
design-system/colors.schema.json:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://ui.company.com/design-system/colors",
"title": "Design System Colors",
"type": "string",
"enum": [
"primary",
"secondary",
"success",
"danger",
"warning",
"info",
"light",
"dark"
],
"default": "primary"
}components/Button.schema.json:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://ui.company.com/components/Button",
"title": "Button Component",
"type": "object",
"properties": {
"variant": {
"$ref": "https://ui.company.com/design-system/colors",
"description": "按鈕顏色,必須符合設計系統規範"
},
"size": {
"$ref": "https://ui.company.com/design-system/sizes",
"description": "按鈕尺寸"
},
"children": {
"type": "string",
"minLength": 1,
"maxLength": 50,
"description": "按鈕文字"
},
"icon": {
"type": "string",
"pattern": "^[a-z-]+$",
"description": "圖標名稱 (kebab-case)"
},
"loading": {
"type": "boolean",
"default": false
},
"disabled": {
"type": "boolean",
"default": false
}
},
"required": ["children"],
"additionalProperties": false,
"examples": [
{
"variant": "primary",
"size": "md",
"children": "Submit"
},
{
"variant": "danger",
"size": "lg",
"icon": "trash",
"children": "Delete"
}
]
}graph LR
A[JSON Schema] --> B[TypeScript Types]
A --> C[React Components]
A --> D[Storybook Stories]
A --> E[Markdown Docs]
A --> F[Rust Validators]
| 指標 | 傳統方式 | Schema-DD | 提升 |
|---|---|---|---|
| 添加新組件 | 2-3 小時 | 30 分鐘 | 4-6x |
| 修改 Props | 1 小時 | 5 分鐘 | 12x |
| 同步前後端 | 2-3 天 | 實時 | ∞ |
| 文檔更新 | 手動 | 自動 | ∞ |
| 指標 | 傳統方式 | Schema-DD | 改善 |
|---|---|---|---|
| Props 錯誤率 | 15% | 0.1% | 150x |
| 文檔準確性 | 60% | 100% | Perfect |
| 設計系統違規 | 常見 | 不可能 | 100% |
| 跨平台一致性 | 80% | 100% | Perfect |
組件數量 vs 維護時間:
- 傳統方式: 50 組件 = 每月 40 小時維護
- Schema-DD: 50 組件 = 每月 5 小時維護
成本降低: 88%
// src/schemas/registry.ts
import buttonSchema from './components/Button.schema.json';
import inputSchema from './components/Input.schema.json';
// ... 50+ schemas
export const COMPONENT_SCHEMAS = {
Button: buttonSchema,
Input: inputSchema,
// ...
};
// 運行時驗證
export function validateComponentProps(
component: string,
props: unknown
): boolean {
const schema = COMPONENT_SCHEMAS[component];
const validate = ajv.compile(schema);
return validate(props);
}// ✅ 合法: 使用設計系統定義的顏色
{
"variant": "primary"
}
// ❌ 非法: Schema 自動拒絕
{
"variant": "custom-blue" // Error: must be one of enum values
}結果: 設計師再也不用擔心開發者「自創」顏色
用戶配置 (JSON):
{
"dashboard": {
"layout": "grid",
"widgets": [
{
"type": "Chart",
"props": {
"chartType": "line",
"dataSource": "sales"
}
},
{
"type": "Table",
"props": {
"columns": ["name", "value"],
"dataSource": "users"
}
}
]
}
}自動驗證 + 渲染:
// 驗證配置
const isValid = validateComponentProps('Dashboard', config.dashboard);
// 動態渲染
function renderDashboard(config: DashboardConfig) {
return (
<Grid>
{config.widgets.map(widget => {
const Component = COMPONENTS[widget.type];
return <Component {...widget.props} />;
})}
</Grid>
);
}同一個 Schema,三個平台:
// Web (React)
<Button variant="primary" size="md">Submit</Button>
// React Native
<Button variant="primary" size="md">Submit</Button>
// Rust (後端驗證)
let config = json!({"variant": "primary", "size": "md", "children": "Submit"});
validate_button(&config)?;保證: Props 100% 一致,不可能出現平台差異
"再也不用擔心 Props 類型不一致了,Schema 改了,TypeScript 自動跟著變"
"驗證前端傳來的配置超簡單,一行
validate()就搞定"
"終於可以強制執行設計規範了,開發者想違規都不行"
"開發速度快了 4 倍,3 個月完成了原本 8 個月的工作量"
投入:
- Schema 設計: 2 週
- 自動化工具: 1 週
- 團隊培訓: 3 天
產出:
- 開發效率提升: 4-6x
- 維護成本降低: 88%
- Bug 減少: 95%
- 文檔準確: 100%
ROI: 投入 1 個月,回報 6-12 個月開發時間
- ✅ 從設計系統開始: 先定義 colors/sizes/spacing,再定義組件
- ✅ 漸進式採用: 新組件用 Schema,舊組件逐步遷移
- ✅ 自動化優先: CI/CD 自動驗證 + 生成,人工零介入
- ✅ 團隊培訓: 1 天 workshop,讓所有人理解 Schema-DD
⚠️ Schema 版本管理: 初期沒做好,導致 Breaking Changes 混亂⚠️ Schema 文檔: 應該在 Schema 中寫更詳細的 description⚠️ 測試覆蓋: 應該為每個 Schema example 自動生成測試
- Schema Registry:
../../examples/schema-registry.rs - Component Pattern:
../../methodology/component-library-pattern.md - JSON-as-Object:
../../methodology/json-as-object.md
Schema-Driven Component Library 成功關鍵:
- Schema Registry: 集中管理所有組件規格
- 設計系統強制: $ref 引用保證一致性
- 自動化一切: Types/Docs/Stories/Validation 全自動
- 跨平台對齊: 同一個 Schema,所有平台通用
- ROI 超高: 1 個月投入,回報 6-12 個月
效率提升: 4-6 倍 維護成本: 降低 88% 文檔準確: 100%
這就是 Schema-DD 在組件庫的殺手級應用!