Yang

Feature Sliced 架构设计

0 views
2 mins
Feature Sliced 架构设计

什么是 Feature Sliced?

FSD - Feature Sliced - (功能切片设计) 是一种用于构建前端应用程序的架构方法。可以将其理解为前端项目结构、代码约定和规则的规范。它的目的是让项目在应对不断变化的业务需求时,更加易于理解和组织,便于扩展和维护。

是否适合你的项目?

  • 这种架构方法论只适用于前端项目,不适用与后端
  • 仅适用于面向用户的应用程序,而不适用与库或者UI工具包
  • 小项目可能不需要 FSD,并且可能会额外提高项目的复杂性
  • 特别复杂的项目,也依然可以应用 FSD的架构模式

无论你是哪种项目,是否适合,都可以了解下 FSD,从其中或者灵感💡

分层结构

CleanShot 2024-05-29 at 13.54.51@2x.png

在 FSD 架构中,可以分为从下到下三层,分别为 LayersSlices 以及 Segments Layers 是顶层目录,它最多六层(之前是七层),并且是标准化的,但是其中一些是可选的。

在 FSD 中,一个项目由 Layers 组成, Layers Slices 组层, Slices Segments 组成。

Layers

  • app : 应用程序开始的地方,这里定义 AppProvider Routers 、全局样式、全局类型声明等,是应用程序的入口。
  • pages : 页面入口,将 entities(实体) features(特征) widgets(小部件) 组合起来的完整页面,对应着应用路由,这里组合成的东西提供给 app 使用
  • widgets : 小部件组合层,并非 UI Compoennts,将 entities features 组合成有意义的业务模块,例如 用户信息卡片、问题列表、用户设置等
  • features : 与用户有交互的模块,可以为用户带来价值的行为,例如发送评论、加入购物车、搜索等,该层可根据项目具体需求选择
  • entities : 业务实体层,不同实体的定义目录,例如用户、产品、订单等,也是可选层
  • shared : 共享模块,与项目、业务的具体内容分离,可重复使用的功能,例如组件库、工具库、API等

[!TIP] Layers并非是固定不变的,对于不复杂的项目或者极其复杂的项目来说,可以根据项目自身需求动态的减少或者增加 Layers

分层结构 FSD 的一个关键特点: entities 不能使用来自 features 的功能,因为 fetures 在层次结构中层级更高,层级由高到低的顺序如图所示: CleanShot 2024-05-29 at 13.56.11@2x.png 层级低的 Layer 不能引用层级高的 Layer ,例如:

可以在 pages 目录中使用 features 或者 shared 中的模块 但是无法在 entities 中引用 features

这样做的目的是为了保持引用关系只朝一个方向线性流动,层级越低,其改动的风险就会越大,因为它相当于基础的东西,会被很多地方所使用

CleanShot 2024-05-29 at 14.09.55@2x.png

pages

pages 对应着应用程序的路由结构,在FSD架构中, pages 之间不可以互相引用,一个页面不能从另外一个页面目录中导入代码

shared

共享层与其他层不同在于它不包含 Slices ,而是直接由 Segment 组成 CleanShot 2024-05-28 at 23.42.29@2x.png


  • UI : 基础组件,例如不包含业务逻辑的 Buttom Input Modal 组件等
  • API : 封装的 fetch 请求方法,用来与后端API交互
  • Config :环境变量、应用程序配置等
  • Il8n :多语言配置(如果有的话)
  • Router :路由配置(如果有的话)
  • Constant :业务常量

同样在 Shared 中, Segment 并不是一成不变的,可以项目需求增加或者减少,但需要注意,定义 Segemnt 时需要考虑的一个重点是: Segment 名称应该描述 为什么而不是 是什么 components hooks models 这样的名称尽量不要使用

Slices

Slices (切片) 由 Segment (段)组成,主要目的是按照业务领域代码进行分区,通过将逻辑相关的模块放在一起,让代码更容易导航,切片不能在同一层上使用其他切片,这有助于实现 高内聚性低耦合性

切片中连接的并不是抽象的逻辑实物,而是具体的业务实体(entities)

Slices 有一些需要注意的事项:

  • 同一 Layer 的 Slices 不能相互引用
  • 在大多数情况下,应该避免在 Slices 中嵌套,并且只使用文件夹进行结构分组

一个较为完整的 Slices 示例:

CleanShot 2024-05-29 at 15.48.03@2x.png

Segment

Segment 是微小的模块,目的在于帮助切片内的代码分离,最常见的 Segment UI Model(store、actions) Api Lib ,同时还可以根据需要省略一些或者添加其他模块

  • ui: 只包含UI视图,不包含业务逻辑
  • lib: 基础工具库
  • config:配置
  • api: api 请求的逻辑,或者 api 实例

统一导出索引、公共API

每个 pages slices 都应该有一个统一的对外导出索引,一般情况下为当前目录下的 index 文件,在这个文件下统一进行模块的导出,与其他模块进行引用交互。而对于没有 slices shared 层,则不需要统一导出索引,只需要为每个模块的定义单独的导出。

 
1
└── src
2
├── app
3
├── entities
4
│ ├── account
5
│ │ └── index.ts
6
│ ├── post
7
│ │ └── index.ts
8
│ ├── product
9
│ │ └── index.ts
10
│ └── user
11
│ └── index.ts
12
├── features
13
│ ├── auth-login
14
│ │ └── index.ts
15
│ ├── create-account
16
│ │ └── index.ts
17
│ └── payment
18
│ └── index.ts
19
├── pages
20
│ ├── about
21
│ │ └── index.ts
22
│ ├── cart
23
│ │ └── index.ts
24
│ ├── home
25
│ │ └── index.ts
26
│ ├── posts
27
│ │ └── index.ts
28
│ └── user
29
│ └── index.ts
30
├── shared
31
│ ├── api
32
│ │ └── index.ts
33
│ ├── config
34
│ │ └── index.ts
35
│ └── ui
36
│ └── index.tsx
37
└── widgets
38
├── cart-box
39
├── footer
40
└── header

公共API简化了导入和导出的工作,在对项目进行修改时,可以方便的统一修改,而不需要在代码的各个地方进行修改

常规架构

在许多语言和框架中,大家都习惯将类似功能的代码放在一起,例如

 
1
├── src
2
│ ├── actions
3
│ ├── common
4
│ ├── components
5
│ ├── controller
6
│ ├── pages
7
│ ├── services
8
│ └── utils
9

相信大家很熟悉这种目录结构了,常规架构简单易懂,一眼就能看出来某个模块是用来做什么的。 但是明显的缺点就是模块之间的隐式连接和模块混乱,使得项目会变得难以维护,随着时间的推移,常规架构的缺点就会变得越来越明显,项目发展的越久,架构就会越来越难以梳理和维护。

  • 有时候不清楚一个应该把功能模块放在模块还是组件中
  • 在另一个模块中使用其他模块时遇到困难
  • 存储业务实体的问题

FSD 主要解决的问题

Feature-SLiced 架构的主要目的在于实现 高内聚性低耦合性 , 它根据代码的作用以及对项目的贡献来决定它们的位置。 在 FSD 中,较低的层一般是属于比较抽象的,它们可以在较高的层中重复、多次的使用,这样就实现了 抽象多态 因为高层可以重复使用低层,所以也实现了 继承

通过公共API index ,统一模块对外的入口,限制对Slice和Segment内部的访问,实现了 封装

所以可以发现,FSD 通过约定的方式,就已经在结构层面实现了 多态封装继承抽象的概念,这些概念确保了代码的隔离、可重用性和多功能性。

FSD 通过其概念和标准,可以避免常规架构存在的问题,但是需要前期的了解

优点

统一化

  • 代码按照影响范围(Layers)、领域(Slices)、和 段(Segment)进行组织,一个标准化的架构 逻辑的受控重用
  • 每个组件模块都有其目的和可预测的依赖关系
  • 便于尊徐DRY原则和适应可能性之间保持平衡 功能变化和重构时的稳定性 特定层上的模块不能使用同一层上的其他模块,也不能使用上面的层,可以进行单独的、不影响其他模块的修改,从而避免产生意外的后果。 业务和用户需求导向 当应用程序被分割成业务领域时,通过浏览代码就可以发现和深入的了解项目的所有功能。

缺点

  • 与常规架构相比,有一定的上手成本
  • 需要团队统一规范和遵守
  • 不太适合 MVP 项目或者小的项目,长期来看并没有多大的好处,还需额外付出
  • 出现问题需要理科解决,而不能等到“以后”

Feature-Sliced 架构并非适用与所有的前端项目,尤其当前大多数框架、库都提供了自己的官方标准模板,例如 NextJS 和 Sveltekit 等更是对目录结构的要求有一些限制。 同时,FSD 架构的应用还需要考虑到项目、团队等诸多要素,所以 FSD 也许并不是最适合你的项目大,但是它的概念以及一些规范,则非常适合去学习和借鉴并应用到自己的项目中。

示例

TODO:占个坑,等应用了之后再来补充。

参考