业务无关的、生产就绪的前端模板,基于 TypeScript、React、shadcn/ui 构建,遵循领域驱动设计 (DDD) 和整洁架构 (Clean Architecture) 原则。
这是一个业务无关的、生产就绪的前端模板,基于 TypeScript、React 和 shadcn/ui 构建,遵循领域驱动设计 (DDD) 和整洁架构 (Clean Architecture) 原则。
此模板为任何前端应用提供坚实的架构基础。它完全业务无关,意味着您可以将其用作任何项目领域的起点 - 电子商务、SaaS、仪表板或任何 Web 应用。
- ✅ 业务无关 - 纯架构模板,不包含业务逻辑
- ✅ 严格分层 - DDD 四层架构,清晰的依赖关系
- ✅ 类型安全 - TypeScript 严格模式,完整类型覆盖
- ✅ 高可测试 - 34+ 测试文件,覆盖所有架构层
- ✅ 现代化UI - shadcn/ui + Tailwind CSS + 暗黑模式
- ✅ 生产就绪 - 完整的基础设施和最佳实践
基于 DDD 和整洁架构的严格分层:
表现层 (UI 组件)
↓
应用层 (用例 & DTOs)
↓
领域层 (核心业务逻辑)
↑
基础设施层 (技术实现)
依赖规则: 依赖只能向内指向,外层依赖内层,内层不知道外层的存在。
| 分类 | 技术 | 版本 |
|---|---|---|
| 核心 | React | 19.2.0 |
| TypeScript | 4.9.5 | |
| UI | shadcn/ui + Radix UI | 最新 |
| Tailwind CSS | 3.4.0 | |
| lucide-react (图标) | 最新 | |
| 构建 | CRACO | 7.1.0 |
| react-scripts | 5.0.1 | |
| 测试 | Jest | 27.x |
| React Testing Library | 16.3.0 | |
| 其他 | Monaco Editor | 4.7.0 |
| Axios | 1.13.2 |
src/
├── domain/ # 领域层 - 核心业务逻辑
│ ├── entities/ # 具有标识的领域实体
│ ├── valueObjects/ # 不可变值对象
│ ├── repositories/ # 仓储接口
│ └── services/ # 领域服务
│
├── application/ # 应用层 - 用例编排
│ ├── useCases/ # 应用用例
│ ├── dto/ # 数据传输对象
│ ├── providers/ # 服务提供者接口
│ ├── batch/ # 批量处理服务
│ └── streaming/ # 流式处理服务
│
├── infrastructure/ # 基础设施层 - 技术细节
│ ├── repositories/ # 仓储实现 (LocalStorage 等)
│ ├── cache/ # LRU 缓存及 TTL 管理
│ ├── streaming/ # 流式 HTTP 客户端
│ ├── batch/ # 批量操作执行器
│ └── deduplication/ # 请求去重
│
├── components/ # 表现层 - UI 组件
│ ├── ui/ # shadcn/ui 组件 (16个)
│ ├── theme-provider.tsx # 主题管理
│ └── ... # 功能组件
│
├── hooks/ # 自定义 React Hooks
├── contexts/ # React 上下文
├── services/ # 外部服务适配器
├── types/ # TypeScript 类型定义
├── utils/ # 工具函数
└── lib/ # 库配置
- Node.js 16+
- npm 或 yarn
# 克隆仓库 (或作为模板使用)
git clone <your-repo-url>
cd typed-frontend-template
# 安装依赖
npm install
# 启动开发服务器
npm start应用将在 http://localhost:3000 启动
# 开发
npm start # 启动开发服务器
# 测试
npm test # 运行测试 (监听模式)
npm test -- --coverage # 生成覆盖率报告
# 生产
npm run build # 构建生产版本首先定义业务实体和值对象:
// src/domain/entities/Product.ts
export class Product {
constructor(
public readonly id: string,
public name: string,
public price: number
) {}
}
// src/domain/repositories/interfaces.ts
export interface IProductRepository {
save(product: Product): Promise<void>;
findById(id: string): Promise<Product | null>;
findAll(): Promise<Product[]>;
delete(id: string): Promise<void>;
}定义应用的用例:
// src/application/useCases/ProductUseCases.ts
export class CreateProductUseCase {
constructor(private repository: IProductRepository) {}
async execute(data: CreateProductDTO): Promise<Product> {
const product = new Product(
generateId(),
data.name,
data.price
);
await this.repository.save(product);
return product;
}
}提供具体实现:
// src/infrastructure/repositories/LocalStorageProductRepository.ts
export class LocalStorageProductRepository implements IProductRepository {
private readonly storageKey = 'products';
async save(product: Product): Promise<void> {
const products = await this.findAll();
const index = products.findIndex(p => p.id === product.id);
if (index >= 0) {
products[index] = product;
} else {
products.push(product);
}
localStorage.setItem(this.storageKey, JSON.stringify(products));
}
async findById(id: string): Promise<Product | null> {
const products = await this.findAll();
return products.find(p => p.id === id) || null;
}
async findAll(): Promise<Product[]> {
const data = localStorage.getItem(this.storageKey);
return data ? JSON.parse(data) : [];
}
async delete(id: string): Promise<void> {
const products = await this.findAll();
const filtered = products.filter(p => p.id !== id);
localStorage.setItem(this.storageKey, JSON.stringify(filtered));
}
}使用 shadcn/ui 组件创建 UI:
// src/components/ProductList.tsx
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
export function ProductList() {
const { products, createProduct, deleteProduct } = useProducts();
return (
<div className="space-y-4">
<Button onClick={createProduct}>添加产品</Button>
{products.map(product => (
<Card key={product.id}>
<h3>{product.name}</h3>
<p>¥{product.price}</p>
<Button onClick={() => deleteProduct(product.id)}>删除</Button>
</Card>
))}
</div>
);
}通过全面的测试确保质量:
// src/domain/entities/__tests__/Product.test.ts
describe('Product', () => {
it('应该创建包含 id、名称和价格的产品', () => {
const product = new Product('1', '笔记本电脑', 999);
expect(product.id).toBe('1');
expect(product.name).toBe('笔记本电脑');
expect(product.price).toBe(999);
});
});模板包含 16 个预配置的 shadcn/ui 组件:
- 表单: Button, Input, Textarea, Label, Select, Switch
- 布局: Dialog, Sheet, Tabs, Separator, Scroll Area
- 反馈: Tooltip, Badge, Skeleton
所有组件支持:
- 暗黑/亮色主题切换
- 完整的 TypeScript 类型
- 可访问性 (ARIA 标准)
- 通过 Tailwind CSS 自定义
模板包含覆盖所有层的全面测试:
34+ 测试文件:
├── 领域层 (3 个测试套件)
│ ├── 实体
│ ├── 值对象
│ └── 领域服务
├── 应用层 (5 个测试套件)
│ ├── 用例
│ ├── DTOs
│ └── 服务
├── 基础设施层 (7 个测试套件)
│ ├── 仓储
│ ├── 缓存
│ ├── 流式处理
│ └── 去重
└── 表现层 (8+ 个测试套件)
└── 组件
模板演示了几个关键设计模式:
- 仓储模式 - 抽象数据访问
- 适配器模式 - 外部服务集成
- 工厂模式 - 对象创建
- 策略模式 - 可互换的算法
- 观察者模式 - 基于事件的更新 (通过 React Context)
架构严格遵循 SOLID 原则:
- Single Responsibility (单一职责) - 每个类只有一个职责
- Open/Closed (开闭原则) - 易于扩展而无需修改
- Liskov Substitution (里氏替换) - 接口可互换
- Interface Segregation (接口隔离) - 小而专注的接口
- Dependency Inversion (依赖倒置) - 依赖抽象而非具体
- CLAUDE.md - Claude Code 详细指南
- PROJECT_SUMMARY.md - 架构深度解析
- VALIDATION_REPORT.md - 架构验证报告
这是一个模板项目。欢迎:
- Fork 它
- 根据需求定制
- 移除示例业务逻辑
- 添加你自己的领域模型
MIT License - 可以自由将此模板用于任何项目。
使用 DDD + 整洁架构构建 ❤️