Feature-Sliced Design (FSD) là gì?
Feature-Sliced Design (FSD) là một phương pháp luận (methodology) tổ chức cấu trúc thư mục cho các ứng dụng frontend hiện đại. Thay vì gom nhóm tệp tin theo kỹ thuật (components, hooks, apis), FSD định hướng phân rã mã nguồn dựa trên nghiệp vụ (business domain) và mức độ trừu tượng.
Kiến trúc FSD chia dự án thành 3 thực thể phân cấp:
- Layers (Lớp): Cấp độ cao nhất, sắp xếp theo mức độ ảnh hưởng của mã nguồn. Có 6 lớp cơ bản (Shared, Entities, Features, Widgets, Views, App).
- Slices (Lát cắt): Cấp độ nghiệp vụ (ví dụ: auth, post, comment).
- Segments (Phân đoạn): Phân chia chi tiết kỹ thuật bên trong slice (ui, model, api, lib).
Dưới đây là sơ đồ luồng phụ thuộc một chiều nghiêm ngặt (Strict One-way Dependency) của FSD:
│
▼
Views (Từng trang cụ thể)
│
▼
Widgets (Sidebar, Header, Footer)
│
▼
Features (Tác vụ: LikePost, LoginForm)
│
▼
Entities (Model/Dữ liệu: Post, User)
│
▼
Shared (UI components dùng chung, Utils)
Cách ánh xạ FSD vào cấu trúc thư mục của Next.js (App Router)
Với Next.js App Router, hệ thống định tuyến (routing) hoạt động theo tệp tin trong thư mục app/. Để áp dụng FSD một cách chuẩn chỉ mà không làm vỡ cơ chế định tuyến của Next.js, chúng ta triển khai cấu trúc như sau:
src/
├── app/ # Lớp App (chứa root layout, global providers, global CSS)
│ ├── layout.tsx
│ ├── page.tsx
│ ├── posts/
│ │ └── [slug]/
│ │ └── page.tsx # Chỉ import và gọi Component từ lớp Views
├── views/ # Lớp Views (tổ chức giao diện nguyên trang)
│ └── post-detail/
│ ├── index.ts
│ └── ui/
│ ├── PostDetailView.tsx
│ └── PostDetailArticle.tsx
├── widgets/ # Lớp Widgets (gộp các Features và Entities lại)
│ └── home-sidebar/
├── features/ # Lớp Features (các tương tác, chức năng)
│ └── post-like/
├── entities/ # Lớp Entities (quản lý kiểu dữ liệu, API nghiệp vụ)
│ ├── post/
│ └── user/
└── shared/ # Lớp Shared (các thành phần dùng chung cấp thấp)
├── ui/ # Button, Avatar, Input dùng chung
└── lib/ # Helpers, Axios/Fetch client
Quy tắc vàng: Next.js app/posts/[slug]/page.tsx chỉ là một lớp vỏ định tuyến cực kỳ mỏng. Nó nhận tham số `params`, sau đó gọi component `PostDetailView` từ `src/views/post-detail` và truyền dữ liệu xuống. Toàn bộ logic nghiệp vụ thực tế nằm bên trong `src/views/` trở xuống.
Nguyên tắc cốt lõi: Public API (index.ts)
Mỗi slice phải khai báo một tệp tin index.ts đóng vai trò là Public API. Chỉ những hàm, component, hay type nào được `export` trong `index.ts` mới được phép sử dụng ở các slice/layer khác. Việc truy cập trực tiếp vào các tệp tin con (ví dụ: import { Avatar } from "@/shared/ui/Avatar/Avatar") bị cấm hoàn toàn. Thay vào đó phải gọi qua Public API: import { Avatar } from "@/shared".
Phân tích Ưu và Nhược điểm của FSD
Ưu điểm
- Tách biệt mối quan tâm cực kỳ rõ ràng: Mã nguồn của bạn không bị biến thành một "bãi rác" components khi dự án phình to.
- Tránh phụ thuộc vòng (Circular Dependencies): Nhờ quy tắc phụ thuộc một chiều (layer trên chỉ được import layer dưới, không import chéo hoặc import ngược lên), mã nguồn luôn đảm bảo tính sạch sẽ và dễ refactor.
- Linh hoạt và khả năng tái sử dụng cao: Việc thay đổi logic trong một feature (ví dụ: nút Like bài viết) không bao giờ ảnh hưởng đến các lớp dữ liệu cơ bản (Entities).
Nhược điểm
- Độ dốc học tập (Learning Curve) cao: Đòi hỏi các lập trình viên mới gia nhập đội ngũ phải nắm vững triết lý thiết kế và quy tắc nghiêm ngặt của FSD.
- Viết nhiều code boilerplate hơn: Bạn cần tạo nhiều file
index.tsđể làm Public API cho từng module nhỏ. - Độ sâu thư mục lớn: Việc tìm kiếm tệp tin đôi khi đòi hỏi phải đi qua nhiều tầng thư mục con (`features/post/ui/...`).
Áp dụng FSD trong Hệ thống Supper Blogs
Hệ thống Supper Blogs của chúng ta đang áp dụng chuẩn FSD này:
- Các thành phần giao diện gốc như
Avatar,ShareButtonsđược xếp vàoshared/ui/. - Logic hiển thị thông tin bài viết và cấu trúc dữ liệu của bài viết nằm tại
entities/post. - Chức năng tương tác như Thích bài viết (`PostLikeCheck`, `ToggleLike`) hay bình luận (`PostDetailComments`) được xếp tại lớp
features/post. - Sidebar hiển thị danh sách bài viết nổi bật kết hợp quảng cáo và chủ đề gợi ý nằm tại
widgets/home-sidebar. - Các trang đọc chi tiết được tổ chức tại
views/post-detailvàviews/home.
Bình luận (0)
Đang tải bình luận...