当项目从"几个人"扩展到"几十人",从"几个页面"扩展到"几十个页面",代码组织的质量直接决定了开发效率和维护成本。传统的"按文件类型组织"方式(components/、pages/、utils/、hooks/)会让代码随着规模增长而逐渐失控------修改一个功能需要跨多个目录切换文件,模块之间的边界模糊不清。本文从模块化的层次出发,深入讲解按功能组织(Feature-Based) 的目录结构设计,引入 Feature-Sliced Design(FSD) 这一现代化的前端架构方法论,并通过一个完整的电商项目示例,展示如何让大型前端项目的代码"清晰、可控、可扩展"。
一、模块化的层次与价值
模块化不是"把代码拆成多个文件",而是有层次、有规则地组织代码。
模块化的五个层次:

2025 年,前端架构设计的核心趋势是按业务领域而非技术类型组织代码。这种转变的本质,是将代码组织的视角从"技术栈"转向"业务域"。
二、按文件类型组织 vs 按功能组织
这是前端目录结构设计中最根本的选择。
2.1 按文件类型组织(Type-Based)
text
src/
├── components/ # 所有组件(几十个文件混在一起)
│ ├── Button.tsx
│ ├── Header.tsx
│ ├── ProductCard.tsx
│ └── ...
├── pages/ # 所有页面
├── hooks/ # 所有自定义 Hook
├── utils/ # 所有工具函数
├── types/ # 所有类型定义
└── api/ # 所有 API 调用
优点:结构简单,新手容易理解。
缺点:修改一个功能需要跨 4-5 个目录;随着项目增长,components/ 目录会变得臃肿不堪;模块边界模糊,容易产生循环依赖。
2.2 按功能组织(Feature-Based)
text
src/
├── features/ # 按功能模块组织
│ ├── auth/ # 认证功能(登录、注册、找回密码)
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── api/
│ │ └── types/
│ ├── product/ # 商品功能
│ └── cart/ # 购物车功能
├── shared/ # 跨功能共享
│ ├── ui/
│ ├── utils/
│ └── types/
└── app/ # 应用配置
优点:每个功能模块高度内聚;修改一个功能只需在一个目录内操作;模块边界清晰,易于团队分工。
缺点:需要更严格的设计规范;初期设计成本较高。
三、Feature-Sliced Design(FSD):现代化的前端架构方法论
Feature-Sliced Design(FSD) 是一套专为前端项目设计的架构方法论,它通过明确的层(Layers)、切片(Slices)和段(Segments)来组织代码。简单来说,它是一套关于如何组织代码的规则和约定。
FSD 的核心目标是将前端应用按照业务逻辑和职责范围进行划分。它的价值在于:将架构意图转化为文件夹结构和导入规则,让系统自然地保持整洁。
3.1 FSD 的七层模型
FSD 将代码库分为七个层次,从下到上依次是:

⚠️ 关键约束:依赖关系是单向的------高层可以依赖低层,但低层绝对不能依赖高层。
3.2 FSD 的核心概念
(1)层(Layers) :按影响范围(Scope of Influence)划分------app 影响整个应用,shared 只提供基础能力。
(2)切片(Slices) :按业务领域(Domain)划分------auth、product、order 等。
(3)段(Segments) :按技术目的(Technical Purpose)划分------ui/、model/、api/、lib/ 等。
每个切片的内部结构遵循统一的段划分:
text
features/auth/
├── ui/ # UI 组件(LoginForm、RegisterForm)
├── model/ # 状态管理(store、actions、reducers)
├── api/ # API 调用(loginApi、registerApi)
├── lib/ # 工具函数(token utils)
└── types/ # 类型定义(AuthTypes)
3.3 FSD 的目录结构示例
text
src/
├── app/ # 应用层
│ ├── App.tsx
│ ├── main.tsx
│ └── providers/ # Redux Provider、Theme Provider 等
│
├── pages/ # 页面层
│ ├── home-page/
│ ├── product-detail-page/
│ └── checkout-page/
│
├── widgets/ # 功能区块层
│ ├── header/
│ │ ├── ui/
│ │ └── lib/
│ ├── sidebar/
│ └── product-gallery/
│
├── features/ # 功能层
│ ├── auth/
│ │ ├── ui/
│ │ ├── model/
│ │ └── api/
│ ├── add-to-cart/
│ ├── search-products/
│ └── order-checkout/
│
├── entities/ # 实体层
│ ├── user/
│ ├── product/
│ └── order/
│
└── shared/ # 共享层
├── ui/ # 基础 UI 组件(Button、Input、Modal)
├── lib/ # 工具函数(formatDate、debounce)
├── api/ # API 客户端配置
└── config/ # 全局常量
3.4 FSD 的导入规则
typescript
// ✅ 正确:features 可以导入 entities 和 shared
import { User } from '@/entities/user'
import { Button } from '@/shared/ui'
// ✅ 正确:pages 可以导入 features 和 widgets
import { LoginForm } from '@/features/auth'
import { Header } from '@/widgets/header'
// ❌ 错误:entities 不能导入 features(低层不能依赖高层)
import { LoginForm } from '@/features/auth' // 禁止!
// ❌ 错误:features 之间不能直接导入(同一层之间需要通信)
import { Cart } from '@/features/cart' // 禁止!应通过事件或共享状态通信
四、实战:从零设计电商项目的目录结构
假设我们要设计一个电商前端项目的目录结构,按照 FSD 方法论进行组织:
text
my-ecommerce/
├── apps/ # 多个应用(Monorepo 场景)
│ ├── web/ # 主 Web 应用
│ │ └── src/
│ │ ├── app/
│ │ ├── pages/
│ │ ├── widgets/
│ │ ├── features/
│ │ ├── entities/
│ │ └── shared/
│ └── admin/ # 管理后台
│
├── packages/ # 共享包
│ ├── ui/ # 共享 UI 组件库
│ ├── utils/ # 共享工具函数
│ └── config/ # 共享配置
│
└── tooling/ # 工具配置
├── eslint/
└── typescript/
核心设计决策:
应用层(app) :路由配置、全局布局、Provider 初始化
页面层(pages) :每个页面一个目录,组合 widgets 和 features
功能层(features) :独立的业务功能,如 auth、search、checkout
实体层(entities) :核心业务实体,如 product、order、user
共享层(shared) :基础 UI 组件、工具函数、API 客户端
五、模块化的最佳实践
从第一天就开始模块化:不要让项目"先跑起来再重构",模块化应该从项目启动时就纳入设计。
定义清晰的模块边界:每个模块只暴露必要的公共 API(通过 index.ts 控制导出)。
遵循单向依赖:低层永远不依赖高层。
定期审视模块边界:每季度评估一次模块划分是否仍然合理。
使用工具强制执行:ESLint 插件(如 eslint-plugin-boundaries)可以在 CI 中自动检查模块依赖规则。
六、小结
模块化层次:组件级 → 页面级 → 功能级 → 应用级,逐层提升复用性和可维护性。
组织方式对比:按文件类型组织在小项目中简单,但大型项目中容易失控;按功能组织让每个模块高度内聚,修改一个功能只需在一个目录内操作。
Feature-Sliced Design(FSD) :将前端应用按照业务逻辑和职责范围进行划分,通过 层(Layers)+ 切片(Slices)+ 段(Segments) 三维组织代码,将架构意图转化为文件夹结构和导入规则。
FSD 七层模型:app → pages → widgets → features → entities → shared,依赖关系单向,低层不依赖高层。
核心规则:每个模块只暴露必要的公共 API;使用 ESLint 插件强制执行依赖规则。