feature-sliced-design by feature-sliced/skills
npx skills add https://github.com/feature-sliced/skills --skill feature-sliced-design来源 : fsd.how | 严格程度可根据项目规模和团队背景进行调整。
FSD v2.1 的核心原则:“从简单开始,需要时再提取。”
首先将代码放在 pages/ 中。页面间的重复是可以接受的,并不自动需要提取到更低层级。只有当团队一致认为有必要时才进行提取。
并非所有层级都是必需的。 大多数项目可以仅从 shared/、pages/ 和 app/ 开始。只有当 widgets/、features/、entities/ 能提供明确价值时才添加它们。不要“以防万一”地创建空的层级文件夹。
FSD 使用 6 个标准化的层级,并遵循严格的自上而下的导入方向:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
app/ → 应用初始化、提供者、路由
pages/ → 路由级别的组合,拥有自己的逻辑
widgets/ → 跨多个页面复用的大型复合 UI 块
features/ → 可复用的用户交互(仅在 2 个或更多地方使用时)
entities/ → 可复用的业务领域模型(仅在 2 个或更多地方使用时)
shared/ → 不包含业务逻辑的基础设施(UI 套件、工具、API 客户端)
导入规则:模块只能从严格位于其下方的层级导入。禁止同一层级内不同切片之间的交叉导入。
// ✅ 允许
import { Button } from "@/shared/ui/Button"; // features → shared
import { useUser } from "@/entities/user"; // pages → entities
// ❌ 违规
import { loginUser } from "@/features/auth"; // entities → features
import { likePost } from "@/features/like-post"; // features → features
注意:processes/ 层级在 v2.1 中已弃用。有关迁移详情,请阅读 references/migration-guide.md。
编写新代码时,请遵循此决策树:
步骤 1 — 这段代码用在哪里?
pages/ 切片中。insignificant-slice)。步骤 2 — 它是不包含业务逻辑的可复用基础设施吗?
shared/ui/shared/lib/shared/api/ 或 shared/config/shared/auth/shared/api/步骤 3 — 它是一个在 2 个或更多地方复用的完整用户操作,并且团队同意提取它吗?
features/步骤 4 — 它是一个在 2 个或更多地方复用的业务领域模型,并且团队同意提取它吗?
entities/步骤 5 — 它是应用范围的配置吗?
app/黄金法则:当有疑问时,保留在 pages/ 中。仅在团队同意时提取。
| 场景 | 单次使用 | 多次使用(需团队同意) |
|---|---|---|
| 用户资料表单 | pages/profile/ui/ProfileForm.tsx | features/profile-form/ |
| 产品卡片 | pages/products/ui/ProductCard.tsx | entities/product/ui/ProductCard.tsx |
| 产品数据获取 | pages/product-detail/api/fetch-product.ts | entities/product/api/ |
| 认证令牌/会话 | shared/auth/ (始终) | shared/auth/ (始终) |
| 认证登录表单 | pages/login/ui/LoginForm.tsx | features/auth/ |
| CRUD 操作 | shared/api/ (始终) | shared/api/ (始终) |
| 通用卡片布局 | — | shared/ui/Card/ |
| 模态管理器 | — | shared/ui/modal-manager/ |
| 模态内容 | pages/[page]/ui/SomeModal.tsx | — |
| 日期格式化工具 | — | shared/lib/format-date.ts |
这些规则是 FSD 的基础。违反规则会削弱架构。如果必须打破规则,请确保这是一个有意识的设计决策——记录原因并获得团队共识。
app → pages → widgets → features → entities → shared。禁止向上导入以及同一层级内切片之间的交叉导入。
外部使用者只能从切片的 index.ts 导入。禁止直接导入内部文件。
// ✅ 正确
import { LoginForm } from "@/features/auth";
// ❌ 违规 — 绕过公共 API
import { LoginForm } from "@/features/auth/ui/LoginForm";
RSC / 元框架例外: 在具有明确客户端/服务器边界的环境中,允许拆分入口点(index.client.ts、index.server.ts)。详情请见 references/framework-integration.md。
如果同一层级的两个切片需要共享逻辑,请遵循第 7 节中的解决顺序。不要创建直接导入。
根据文件所代表的业务领域来命名,而不是根据其技术角色。像 types.ts、utils.ts、helpers.ts 这样的技术角色名称会将不相关的领域混合在单个文件中,并降低内聚性。
// ❌ 技术角色命名
model/types.ts ← 哪些类型?用户?订单?混合的?
model/utils.ts
// ✅ 基于领域的命名
model/user.ts ← 用户类型 + 相关逻辑
model/order.ts ← 订单类型 + 相关逻辑
api/fetch-profile.ts ← 目的明确
Shared 仅包含基础设施:UI 套件、工具、API 客户端设置、路由常量、资源。业务计算、领域规则和工作流属于 entities/ 或更高层级。
// ❌ 业务逻辑放在 shared 中
// shared/lib/userHelpers.ts
export const calculateUserReputation = (user) => { ... };
// ✅ 移动到所属领域
// entities/user/lib/reputation.ts
export const calculateUserReputation = (user) => { ... };
首先将代码放在 pages/ 中。仅在真正需要时才提取到更低层级。当提取看起来有价值时,与团队讨论——这是一个影响整个项目的设计决策。
保留在页面中的内容:
演进模式: 从将所有内容放在 pages/profile/ 开始。当另一个页面需要相同的用户数据且团队同意时,将共享模型提取到 entities/user/。保留页面特定的 API 调用和 UI 在页面中。
实体层具有高度可访问性——几乎其他所有层级都可以从它导入,因此变更影响范围广。
shared/ + pages/ + app/ 是有效的 FSD。瘦客户端应用很少需要实体。shared/api 中,将逻辑保留在当前切片的 model/ 段中可能就足够了。shared/api/ 中。 CRUD 是基础设施,不是实体。shared/auth/ 或 shared/api/ 中。 令牌和登录 DTO 依赖于认证上下文,很少在认证之外复用。// ✅ 有效的最小 FSD 项目
src/
app/ ← 提供者、路由
pages/ ← 所有页面级别的代码
shared/ ← UI 套件、工具、API 客户端
// 仅当团队决定需要时才添加层级:
// + widgets/ ← 在 2 个或更多页面中复用的 UI 块
// + features/ ← 在 2 个或更多页面中复用的用户交互
// + entities/ ← 在 2 个或更多页面/功能中复用的领域模型
Steiger 是官方的 FSD linter。关键规则:
insignificant-slice :如果一个实体/功能仅被一个页面使用,建议将其合并到该页面中。
excessive-slicing :当一个层级有太多切片时,建议合并或分组。
npm install -D @feature-sliced/steiger npx steiger src
shared/api/。仅对复杂的事务逻辑才考虑使用实体。user 实体。 令牌和登录 DTO 属于 shared/auth/ 或 shared/api/。user-management/ 拆分为 auth/、profile-edit/、password-reset/)。当同一层级的两个切片需要共享代码时,按顺序尝试这些策略。始终先尝试较早的策略。
entities/。将 UI 保留在功能/部件中。有关每种策略的详细代码示例,请阅读 references/cross-import-patterns.md。
段根据技术目的对切片内的代码进行分组:
ui/ — UI 组件、样式、显示相关代码model/ — 数据模型、状态存储、业务逻辑、验证api/ — 后端集成、请求函数、API 特定类型lib/ — 该切片内部的工具函数config/ — 配置、功能开关始终使用基于领域的名称来描述代码的内容:
model/user.ts ← 用户类型 + 逻辑 + 存储
model/order.ts ← 订单类型 + 逻辑 + 存储
api/fetch-profile.ts ← 资料获取
api/update-settings.ts ← 设置更新
如果一个段只有一个领域关注点,文件名可以与切片名称匹配(例如,features/auth/model/auth.ts)。
Shared 包含不包含业务逻辑的基础设施。它仅按段组织(没有切片)。Shared 内的段可以相互导入。
允许在 shared 中的内容:
ui/ — UI 套件(Button、Input、Modal、Card)lib/ — 工具(formatDate、debounce、classnames)api/ — API 客户端、路由常量、CRUD 助手、基础类型auth/ — 认证令牌、登录工具、会话管理config/ — 环境变量、应用设置assets/ — 图片、字体、图标Shared 可以包含应用感知的代码(路由常量、API 端点、品牌资源、通用类型)。它绝不能包含业务逻辑、功能特定的代码或实体特定的代码。
app → pages → widgets → features → entities → sharedapp/ + pages/ + shared/user.ts、order.ts)。绝不用技术角色(types.ts、utils.ts)。references/migration-guide.md。仅当特定情况适用时才阅读以下参考文件。不要预加载所有参考。
当为 FSD 层级和切片创建、审查或重组文件夹和文件结构时(例如,“设置项目结构”、“这个文件夹放哪里”):→ 阅读 references/layer-structure.md
当解决同一层级切片间的交叉导入问题、评估 @x 模式或处理过度的实体耦合时:→ 阅读 references/cross-import-patterns.md
当从 FSD v2.0 迁移到 v2.1、将非 FSD 代码库转换为 FSD 或弃用 processes 层级时:→ 阅读 references/migration-guide.md
当将 FSD 与特定框架集成(Next.js、Nuxt、Vite、CRA)或配置路径别名时:→ 阅读 references/framework-integration.md
当在 FSD 结构中实现具体的代码模式时,用于认证、API 请求处理、类型定义或状态管理(Redux、React Query):→ 阅读 references/practical-examples.md 注意:如果你在此对话中已加载 layer-structure.md,请避免同时加载此文件。先处理结构,然后在后续步骤中根据需要加载模式。
每周安装量
120
代码仓库
GitHub Stars
11
首次出现
2026年3月9日
安全审计
安装于
gemini-cli116
github-copilot116
kimi-cli115
amp115
cline115
codex115
Source : fsd.how | Strictness can be adjusted based on project scale and team context.
FSD v2.1 core principle: "Start simple, extract when needed."
Place code in pages/ first. Duplication across pages is acceptable and does not automatically require extraction to a lower layer. Extract only when the team agrees it is necessary.
Not all layers are required. Most projects can start with only shared/, pages/, and app/. Add widgets/, features/, entities/ only when they provide clear value. Do not create empty layer folders "just in case."
FSD uses 6 standardized layers with a strict top-down import direction:
app/ → App initialization, providers, routing
pages/ → Route-level composition, owns its own logic
widgets/ → Large composite UI blocks reused across multiple pages
features/ → Reusable user interactions (only when used in 2+ places)
entities/ → Reusable business domain models (only when used in 2+ places)
shared/ → Infrastructure with no business logic (UI kit, utils, API client)
Import rule : A module may only import from layers strictly below it. Cross-imports between slices on the same layer are forbidden.
// ✅ Allowed
import { Button } from "@/shared/ui/Button"; // features → shared
import { useUser } from "@/entities/user"; // pages → entities
// ❌ Violation
import { loginUser } from "@/features/auth"; // entities → features
import { likePost } from "@/features/like-post"; // features → features
Note : The processes/ layer is deprecated in v2.1. For migration details, read references/migration-guide.md.
When writing new code, follow this tree:
Step 1 — Where is this code used?
pages/ slice.insignificant-slice).Step 2 — Is it reusable infrastructure with no business logic?
shared/ui/shared/lib/shared/api/ or shared/config/shared/auth/shared/api/Step 3 — Is it a complete user action reused in 2+ places, and does the team agree to extract it?
features/Step 4 — Is it a business domain model reused in 2+ places, and does the team agree to extract it?
entities/Step 5 — Is it app-wide configuration?
app/Golden Rule: When in doubt, keep it inpages/. Extract only when the team agrees.
| Scenario | Single use | Multi-use (with team agreement) |
|---|---|---|
| User profile form | pages/profile/ui/ProfileForm.tsx | features/profile-form/ |
| Product card | pages/products/ui/ProductCard.tsx | entities/product/ui/ProductCard.tsx |
| Product data fetching | pages/product-detail/api/fetch-product.ts | entities/product/api/ |
These rules are the foundation of FSD. Violations weaken the architecture. If you must break a rule, ensure it is an intentional design decision — document the reason and obtain team consensus.
app → pages → widgets → features → entities → shared. Upward imports and cross-imports between slices on the same layer are forbidden.
External consumers may only import from a slice's index.ts. Direct imports of internal files are forbidden.
// ✅ Correct
import { LoginForm } from "@/features/auth";
// ❌ Violation — bypasses public API
import { LoginForm } from "@/features/auth/ui/LoginForm";
RSC / meta-framework exception: In environments with distinct client/server boundaries, split entry points are permitted (index.client.ts, index.server.ts). See references/framework-integration.md for details.
If two slices on the same layer need to share logic, follow the resolution order in Section 7. Do not create direct imports.
Name files after the business domain they represent, not their technical role. Technical-role names like types.ts, utils.ts, helpers.ts mix unrelated domains in a single file and reduce cohesion.
// ❌ Technical-role naming
model/types.ts ← Which types? User? Order? Mixed?
model/utils.ts
// ✅ Domain-based naming
model/user.ts ← User types + related logic
model/order.ts ← Order types + related logic
api/fetch-profile.ts ← Clear purpose
Shared contains only infrastructure: UI kit, utilities, API client setup, route constants, assets. Business calculations, domain rules, and workflows belong in entities/ or higher layers.
// ❌ Business logic in shared
// shared/lib/userHelpers.ts
export const calculateUserReputation = (user) => { ... };
// ✅ Move to the owning domain
// entities/user/lib/reputation.ts
export const calculateUserReputation = (user) => { ... };
Place code in pages/ first. Extract to lower layers only when truly needed. When extraction seems worthwhile, discuss with the team — this is a design decision that affects the whole project.
What stays in pages:
Evolution pattern: Start with everything in pages/profile/. When another page needs the same user data and the team agrees, extract the shared model to entities/user/. Keep page-specific API calls and UI in the page.
The entities layer is highly accessible — almost every other layer can import from it, so changes propagate widely.
shared/ + pages/ + app/ is valid FSD. Thin-client apps rarely need entities.shared/api and logic in the current slice's model/ segment may be sufficient.shared/api/. CRUD is infrastructure, not entities.shared/auth/ or shared/api/. Tokens and login DTOs are auth-context-dependent and rarely reused outside authentication.// ✅ Valid minimal FSD project
src/
app/ ← Providers, routing
pages/ ← All page-level code
shared/ ← UI kit, utils, API client
// Add layers only when the team decides they are needed:
// + widgets/ ← UI blocks reused in 2+ pages
// + features/ ← User interactions reused in 2+ pages
// + entities/ ← Domain models reused in 2+ pages/features
Steiger is the official FSD linter. Key rules:
insignificant-slice : Suggests merging an entity/feature into its page if only one page uses it.
excessive-slicing : Suggests merging or grouping when a layer has too many slices.
npm install -D @feature-sliced/steiger npx steiger src
shared/api/. Consider entities only for complex transactional logic.user entity just for auth data. Tokens and login DTOs belong in shared/auth/ or shared/api/.user-management/ into auth/, , ).When two slices on the same layer need to share code, try these strategies in order. Always attempt earlier strategies first.
entities/. Keep UI in features/widgets.For detailed code examples of each strategy, read references/cross-import-patterns.md.
Segments group code within a slice by technical purpose:
ui/ — UI components, styles, display-related codemodel/ — Data models, state stores, business logic, validationapi/ — Backend integration, request functions, API-specific typeslib/ — Internal utility functions for this sliceconfig/ — Configuration, feature flagsAlways use domain-based names that describe what the code is about:
model/user.ts ← User types + logic + store
model/order.ts ← Order types + logic + store
api/fetch-profile.ts ← Profile fetching
api/update-settings.ts ← Settings update
If a segment has only one domain concern, the filename may match the slice name (e.g., features/auth/model/auth.ts).
Shared contains infrastructure with no business logic. It is organized by segments only (no slices). Segments within shared may import from each other.
Allowed in shared:
ui/ — UI kit (Button, Input, Modal, Card)lib/ — Utilities (formatDate, debounce, classnames)api/ — API client, route constants, CRUD helpers, base typesauth/ — Auth tokens, login utilities, session managementconfig/ — Environment variables, app settingsassets/ — Images, fonts, iconsShared may contain application-aware code (route constants, API endpoints, branding assets, common types). It must never contain business logic, feature-specific code, or entity-specific code.
app → pages → widgets → features → entities → sharedapp/ + pages/ + shared/user.ts, order.ts). Never technical-role (types.ts, ).Read the following reference files only when the specific situation applies. Do not preload all references.
When creating, reviewing, or reorganizing folder and file structure for FSD layers and slices (e.g., "set up project structure", "where does this folder go"): → Read references/layer-structure.md
When resolving cross-import issues between slices on the same layer, evaluating the @x pattern, or dealing with excessive entity coupling: → Read references/cross-import-patterns.md
When migrating from FSD v2.0 to v2.1, converting a non-FSD codebase to FSD, or deprecating the processes layer: → Read references/migration-guide.md
When integrating FSD with a specific framework (Next.js, Nuxt, Vite, CRA) or configuring path aliases: → Read references/framework-integration.md
When implementing concrete code patterns for authentication, API request handling, type definitions, or state management (Redux, React Query) within FSD structure: → Read references/practical-examples.md Note: If you already loaded layer-structure.md in this conversation, avoid loading this file simultaneously. Address structure first, then load patterns in a follow-up step if needed.
Weekly Installs
120
Repository
GitHub Stars
11
First Seen
Mar 9, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
gemini-cli116
github-copilot116
kimi-cli115
amp115
cline115
codex115
任务估算指南:敏捷开发故事点、计划扑克、T恤尺码法详解
10,500 周安装
应用程序性能优化全栈指南:从分析、数据库到前端与CDN的端到端优化
220 周安装
Encore API 端点开发指南:TypeScript API 创建与配置教程
222 周安装
学术论文LaTeX模板库:Nature/Science/IEEE期刊会议海报申请书模板
218 周安装
安全套件 (security-suite) - 二进制与仓库安全测试、行为契约分析与CI门控工具
223 周安装
tldraw SDK 文档编写指南 - 技术文档规范与MDX组件使用教程
221 周安装
TanStack Query (React Query) 教程:React 异步状态管理与数据获取库
222 周安装
| Auth token/session | shared/auth/ (always) | shared/auth/ (always) |
| Auth login form | pages/login/ui/LoginForm.tsx | features/auth/ |
| CRUD operations | shared/api/ (always) | shared/api/ (always) |
| Generic Card layout | — | shared/ui/Card/ |
| Modal manager | — | shared/ui/modal-manager/ |
| Modal content | pages/[page]/ui/SomeModal.tsx | — |
| Date formatting util | — | shared/lib/format-date.ts |
profile-edit/password-reset/utils.tsreferences/migration-guide.md.