FSD Feature-Sliced Design 功能切片设计 是一种用于构建前端应用程序的架构方法。
可以将其理解为前端项目结构、代码约定和规则的规范。
它的目的是让项目在应对不断变化的业务需求时,更加易于理解和组织,便于扩展和维护。
FSD 是否适合你的项目?
在 FSD 架构中,一个项目由层 Layers
组成,每层 Layers
由切片 Slices
组成,每个切片由段 Segments
组成。
FSD 有一种 Public API 的接口设计方法,通过提供可从外部层访问的入口点并将模块封装在 Slice 下,可以仅公开必要的功能,同时隐藏内部结构。
每个 slices
、 segments
都应该有一个公共 API,一般情况下为当前目录下的 index
文件。
公共 API 是索引文件中公共模块聚合的地方。您可以从切片和段中仅提取必要的函数,并分离不需要的函数。此外,对于外部文件,该索引文件充当入口点。
└── features/ #
├── auth-form / # feature 的内部结构
| ├── ui/ #
| ├── model/ #
| ├── {…}/ #
| ├── index.ts # 入口点及其公共 API
外部接口直接访问模块内部的模式。
改进的好处:通过仅导入允许的内容,您可以一目了然地确定正在访问哪些模块。
// features/todo-create-form/index.ts
export { TodoCreateForm } from "./ui/TodoCreateForm"
- import { TodoCreateForm } from "@features/todo-create-form/ui/TodoCreateForm"
+ import { TodoCreateForm } from "@/features/todo-create-form"
当模块的内部目录结构发生变化时,会影响从外部可见的公共 API 的情况。
改进好处:功能的内部结构不暴露给外部用户,移动或重命名组件不会影响外部用户。
- import { Form } from "features/todo-create-form/ui/form"
+ import { TodoCreateForm } from "features/todo-create-form"
导致名称冲突的情况
// /features/todo-create-form/index.ts
- export { Form } from "./ui/TodoCreateForm"
+ export { Form as TodoCreateForm } from "./ui/TodoCreateForm"
// /features/todo-edit-form/index.ts
- export { Form } from "./ui/TodoCreateForm"
+ export { Form as TodoEditForm } from "./ui/TodoCreateForm"
由于“公共 API”作为索引文件是该模块的入口点,因此应该遵循以下规则:
声明良好的公共接口应该方便应用程序的其余部分使用,并且可以适应模块内部的更改。
公共 API 简化了导入和导出的工作,在对项目进行修改时,可以方便的统一修改,而不需要更改代码中各处的导入。
FSD 的主要目的在于实现高内聚和低耦合 , 它根据代码的作用以及对项目的贡献来决定它们的位置。
FSD 通过约定的方式,在文件结构层面就已经实现了 多态 、封装 、继承 和 抽象 等概念,确保了代码的隔离、可重用性和多功能性。
在 FSD 中,较低的层一般是属于比较抽象的,它们可以在较高的层中重复、多次的使用,这样就实现了 抽象 和多态 因为高层可以重复使用低层,所以也实现了 继承。
通过公共 API index
,统一模块对外的入口,限制对 Slice 和 Segment 内部的访问,实现了 封装
目录管理清晰、耦合度适中
通过 FSD,已经有了分层、切片、分段的标准化管理方法。代码按影响范围(层)、领域(切片)和技术目的(段)进行组织。此外,层之间的依赖关系是单向的,并且切片始终是松散耦合的。
这创建了一个易于每个人理解的标准化架构。我个人觉得它融合了 layered architecture
、package by feature
两者的思想,很容易想象,也有一种统一感
业务和用户需求导向
当应用程序被分割成业务领域时,通过浏览代码就可以发现和深入的了解项目的所有功能
功能变化和重构时的稳定性
由于层与层之间的依赖关系以及公共 API 的思想,每个组件模块都有其目的和可预测的依赖关系。该设计允许我们可以安心地进行更改
拥有支持开发的工具
拥有相关的支持工具来加速开发,例如 Lint 和 IDE 插件和扩展
可以使用 feature-sliced/eslint-config 自动检查层之间的依赖关系和公共 API 规则
写在最后,没有银弹
我认为前端架构没有正确的答案,Feature-Sliced 架构也并非适用于所有的前端项目
尤其当前大多数框架、库都提供了自己的官方标准模板,例如 NextJS 和 Sveltekit 等更是对目录结构的要求有一些限制。 同时,FSD 架构的应用还需要考虑到项目、团队等诸多因素
不过,FSD 也许并不是最适合你的项目架构,但是它的概念以及一些规范,也非常适合去学习和借鉴并应用到自己的项目中。