feature-slicing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseFeature-Sliced Design Architecture
Feature-Sliced Design(FSD)架构
Frontend architecture methodology with strict layer hierarchy and import rules for scalable, maintainable applications. FSD organizes code by business domain rather than technical role.
Official Docs: feature-sliced.design | GitHub: feature-sliced
这是一种前端架构方法论,通过严格的层级结构和导入规则打造可扩展、可维护的应用。FSD按照业务领域而非技术职责来组织代码。
官方文档: feature-sliced.design | GitHub: feature-sliced
THE IMPORT RULE (Critical)
核心导入规则
Modules can ONLY import from layers strictly below them. Never sideways or upward.
app → pages → widgets → features → entities → shared
↓ ↓ ↓ ↓ ↓ ✓
✓ ✓ ✓ ✓ ✓ (external only)| Violation | Example | Fix |
|---|---|---|
| Cross-slice (same layer) | | Extract to |
| Upward import | | Move shared code down |
| Shared importing up | | Shared has NO internal deps |
Exception: and have no slices, so internal cross-imports are allowed within them.
app/shared/模块仅能从严格低于自身的层级导入代码,禁止横向或向上导入。
app → pages → widgets → features → entities → shared
↓ ↓ ↓ ↓ ↓ ✓
✓ ✓ ✓ ✓ ✓ (仅外部依赖)| 违规类型 | 示例 | 修复方案 |
|---|---|---|
| 同层跨切片 | | 提取代码至 |
| 向上导入 | | 将共享代码下移 |
| Shared层向上导入 | | Shared层不得依赖内部模块 |
例外情况: 和层没有切片,因此其内部允许跨模块导入。
app/shared/Layer Hierarchy
层级结构
| Layer | Purpose | Has Slices | Required |
|---|---|---|---|
| Initialization, routing, providers, global styles | No | Yes |
| Route-based screens (one slice per route) | Yes | Yes |
| Complex reusable UI blocks (header, sidebar) | Yes | No |
| User interactions with business value (login, checkout) | Yes | No |
| Business domain models (user, product, order) | Yes | No |
| Project-agnostic infrastructure (UI kit, API client, utils) | No | Yes |
Minimal setup: , , — add other layers as complexity grows.
app/pages/shared/| 层级 | 用途 | 是否包含切片 | 是否必填 |
|---|---|---|---|
| 初始化、路由、提供者、全局样式 | 否 | 是 |
| 基于路由的页面(每个路由对应一个切片) | 是 | 是 |
| 复杂可复用UI块(头部、侧边栏) | 是 | 否 |
| 具备业务价值的用户交互(登录、结账) | 是 | 否 |
| 业务领域模型(用户、商品、订单) | 是 | 否 |
| 与项目无关的基础设施(UI组件库、API客户端、工具函数) | 否 | 是 |
最小配置: 、、 —— 随着项目复杂度提升,再添加其他层级。
app/pages/shared/Quick Decision Trees
快速决策树
"Where does this code go?"
「这段代码应该放在哪里?」
Code Placement:
├─ App-wide config, providers, routing → app/
├─ Full page / route component → pages/
├─ Complex reusable UI block → widgets/
├─ User action with business value → features/
├─ Business domain object (data model) → entities/
└─ Reusable, domain-agnostic code → shared/代码放置规则:
├─ 全局配置、提供者、路由 → app/
├─ 完整页面/路由组件 → pages/
├─ 复杂可复用UI块 → widgets/
├─ 具备业务价值的用户操作 → features/
├─ 业务领域对象(数据模型) → entities/
└─ 可复用、与领域无关的代码 → shared/"Feature or Entity?"
「是Feature还是Entity?」
| Entity (noun) | Feature (verb) |
|---|---|
| |
| |
| |
| |
Rule: Entities represent THINGS with identity. Features represent ACTIONS with side effects.
| Entity(名词,代表事物) | Feature(动词,代表动作) |
|---|---|
| |
| |
| |
| |
规则: Entity代表具有独立标识的事物。Feature代表带有副作用的动作。
"Which segment?"
「该用哪个子模块?」
Segments (within a slice):
├─ ui/ → React components, styles
├─ api/ → Backend calls, data fetching, DTOs
├─ model/ → Types, schemas, stores, business logic
├─ lib/ → Slice-specific utilities
└─ config/ → Feature flags, constantsNaming: Use purpose-driven names (, ) not essence-based (, ).
api/model/hooks/types/切片内的子模块:
├─ ui/ → React组件、样式
├─ api/ → 后端调用、数据获取、DTO
├─ model/ → 类型、 schema、状态管理、业务逻辑
├─ lib/ → 切片专属工具函数
└─ config/ → 功能开关、常量命名规则: 使用基于用途的命名(如、)而非基于本质的命名(如、)。
api/model/hooks/types/Directory Structure
目录结构
src/
├── app/ # App layer (no slices)
│ ├── providers/ # React context, QueryClient, theme
│ ├── routes/ # Router configuration
│ └── styles/ # Global CSS, theme tokens
├── pages/ # Page slices
│ └── {page-name}/
│ ├── ui/ # Page components
│ ├── api/ # Loaders, server actions
│ ├── model/ # Page-specific state
│ └── index.ts # Public API
├── widgets/ # Widget slices
│ └── {widget-name}/
│ ├── ui/ # Composed UI
│ └── index.ts
├── features/ # Feature slices
│ └── {feature-name}/
│ ├── ui/ # Feature UI
│ ├── api/ # Feature API calls
│ ├── model/ # State, schemas
│ └── index.ts
├── entities/ # Entity slices
│ └── {entity-name}/
│ ├── ui/ # Entity UI (Card, Avatar)
│ ├── api/ # CRUD operations
│ ├── model/ # Types, mappers, validation
│ └── index.ts
└── shared/ # Shared layer (no slices)
├── ui/ # Design system components
├── api/ # API client, interceptors
├── lib/ # Utilities (dates, validation)
├── config/ # Environment, constants
├── routes/ # Route path constants
└── i18n/ # Translationssrc/
├── app/ # App层(无切片)
│ ├── providers/ # React上下文、QueryClient、主题
│ ├── routes/ # 路由配置
│ └── styles/ # 全局CSS、主题变量
├── pages/ # Page切片
│ └── {page-name}/
│ ├── ui/ # 页面组件
│ ├── api/ # 加载器、服务端动作
│ ├── model/ # 页面专属状态
│ └── index.ts # 公共API
├── widgets/ # Widget切片
│ └── {widget-name}/
│ ├── ui/ # 组合式UI
│ └── index.ts
├── features/ # Feature切片
│ └── {feature-name}/
│ ├── ui/ # Feature相关UI
│ ├── api/ # Feature相关API调用
│ ├── model/ # 状态、Schema
│ └── index.ts
├── entities/ # Entity切片
│ └── {entity-name}/
│ ├── ui/ # Entity相关UI(卡片、头像)
│ ├── api/ # CRUD操作
│ ├── model/ # 类型、映射器、校验规则
│ └── index.ts
└── shared/ # Shared层(无切片)
├── ui/ # 设计系统组件
├── api/ # API客户端、拦截器
├── lib/ # 工具函数(日期、校验)
├── config/ # 环境配置、常量
├── routes/ # 路由路径常量
└── i18n/ # 国际化翻译Public API Pattern
公共API模式
Every slice MUST expose a public API via . External code imports ONLY from this file.
index.tstypescript
// entities/user/index.ts
export { UserCard } from './ui/UserCard';
export { UserAvatar } from './ui/UserAvatar';
export { getUser, updateUser } from './api/userApi';
export type { User, UserRole } from './model/types';
export { userSchema } from './model/schema';typescript
// ✅ Correct
import { UserCard, type User } from '@/entities/user';
// ❌ Wrong
import { UserCard } from '@/entities/user/ui/UserCard';Avoid wildcard exports — they expose internals and harm tree-shaking:
typescript
// ❌
export * from './ui';
// ✅
export { UserCard } from './ui/UserCard';每个切片必须通过暴露公共API。外部代码仅能从该文件导入内容。
index.tstypescript
// entities/user/index.ts
export { UserCard } from './ui/UserCard';
export { UserAvatar } from './ui/UserAvatar';
export { getUser, updateUser } from './api/userApi';
export type { User, UserRole } from './model/types';
export { userSchema } from './model/schema';typescript
// ✅ 正确
import { UserCard, type User } from '@/entities/user';
// ❌ 错误
import { UserCard } from '@/entities/user/ui/UserCard';避免通配符导出 —— 这会暴露内部实现并影响tree-shaking:
typescript
// ❌ 不推荐
export * from './ui';
// ✅ 推荐
export { UserCard } from './ui/UserCard';Cross-Entity References (@x Notation)
跨Entity引用(@x标记法)
When entities legitimately reference each other, use the notation:
@xentities/
├── product/
│ ├── @x/
│ │ └── order.ts # API specifically for order entity
│ └── index.ts
└── order/
└── model/types.ts # Imports from product/@x/ordertypescript
// entities/product/@x/order.ts
export type { ProductId } from '../model/types';
// entities/order/model/types.ts
import type { ProductId } from '@/entities/product/@x/order';Guidelines: Keep cross-imports minimal. Consider merging entities if references are extensive.
当Entity之间存在合理的相互引用时,使用标记法:
@xentities/
├── product/
│ ├── @x/
│ │ └── order.ts # 专门为order Entity提供的API
│ └── index.ts
└── order/
└── model/types.ts # 从product/@x/order导入typescript
// entities/product/@x/order.ts
export type { ProductId } from '../model/types';
// entities/order/model/types.ts
import type { ProductId } from '@/entities/product/@x/order';指导原则: 尽量减少跨导入。如果引用频繁,考虑合并相关Entity。
Anti-Patterns
反模式
| Anti-Pattern | Problem | Fix |
|---|---|---|
| Cross-slice import | | Extract shared logic down |
| Generic segments | | Use |
| Wildcard exports | | Explicit named exports |
| Business logic in shared | Domain logic in | Move to |
| Single-use widgets | Widget used by one page | Keep in page slice |
| Skipping public API | Import from internal paths | Always use |
| Making everything a feature | All interactions as features | Only reused actions |
| 反模式 | 问题 | 修复方案 |
|---|---|---|
| 同层跨切片导入 | | 提取共享逻辑至更低层级 |
| 通用子模块命名 | 使用 | 改用 |
| 通配符导出 | | 使用显式命名导出 |
| Shared层包含业务逻辑 | 领域逻辑放在 | 迁移至 |
| 单一用途Widget | Widget仅被一个页面使用 | 保留在对应Page切片中 |
| 跳过公共API | 从内部路径导入 | 始终通过 |
| 所有逻辑都作为Feature | 所有交互都定义为Feature | 仅将可复用的动作定义为Feature |
TypeScript Configuration
TypeScript配置
json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}Reference Documentation
参考文档
| File | Purpose |
|---|---|
| references/LAYERS.md | Complete layer specifications, flowcharts |
| references/PUBLIC-API.md | Export patterns, @x notation, tree-shaking |
| references/IMPLEMENTATION.md | Code patterns: entities, features, React Query |
| references/NEXTJS.md | App Router integration, page re-exports |
| references/MIGRATION.md | Incremental migration strategy |
| references/CHEATSHEET.md | Quick reference, import matrix |
| 文件 | 用途 |
|---|---|
| references/LAYERS.md | 完整的层级规范、流程图 |
| references/PUBLIC-API.md | 导出模式、@x标记法、tree-shaking |
| references/IMPLEMENTATION.md | 代码模式:Entity、Feature、React Query |
| references/NEXTJS.md | App Router集成、页面重导出 |
| references/MIGRATION.md | 增量迁移策略 |
| references/CHEATSHEET.md | 速查表、导入矩阵 |
Resources
资源
Official Sources
官方资源
- Official Documentation: https://feature-sliced.design
- GitHub Organization: https://github.com/feature-sliced
- Official Examples: https://github.com/feature-sliced/examples
- Specification: https://feature-sliced.design/docs/reference
Community
社区资源
- Awesome FSD: https://github.com/feature-sliced/awesome (curated articles, videos, tools)