Khi ứng dụng frontend phát triển từ vài màn hình thành một sản phẩm lớn, cấu trúc thư mục lộn xộn sẽ khiến việc sửa lỗi và thêm tính năng trở nên nặng nề. Feature sliced là hướng tổ chức code hiện đại, giúp chia ứng dụng theo nghiệp vụ rõ ràng, kiểm soát phụ thuộc và hỗ trợ đội ngũ làm việc hiệu quả hơn.
Feature sliced là gì trong frontend?
Feature sliced thường được hiểu là Feature-Sliced Design, một phương pháp tổ chức kiến trúc frontend theo các lát cắt nghiệp vụ thay vì chỉ chia theo loại file. Thay vì gom component vào components, API vào services và logic dùng chung vào utils, FSD đặt code vào đúng ngữ cảnh sử dụng.
Trong một dự án nhỏ, cấu trúc truyền thống có thể đủ dùng. Nhưng khi ứng dụng có nhiều page, nhiều form, nhiều trạng thái và nhiều nhóm phát triển cùng tham gia, cách chia đơn giản rất dễ dẫn đến import chéo, trùng logic và khó biết file nào thuộc tính năng nào.
Điểm cốt lõi của Feature sliced là tạo ranh giới giữa các phần trong ứng dụng. Mỗi phần có vai trò riêng, quy tắc phụ thuộc rõ và có thể phát triển độc lập hơn. Nhờ vậy, lập trình viên mới dễ đọc dự án, còn lập trình viên cũ giảm rủi ro làm hỏng phần khác khi chỉnh sửa một tính năng.
Feature-Sliced Design phù hợp với ai?

Phương pháp này phù hợp với lập trình viên React, Vue, Next.js, Nuxt hoặc đội frontend đang xây dựng sản phẩm nhiều nghiệp vụ.
Cấu trúc thư mục cơ bản của Feature sliced
Một dự án dùng Feature sliced thường xoay quanh ba khái niệm: layer, slice và segment. Layer là tầng lớn thể hiện phạm vi ảnh hưởng của code. Slice là lát cắt theo nghiệp vụ hoặc tính năng. Segment là nhóm file bên trong slice theo mục đích kỹ thuật.
Cấu trúc phổ biến có thể gồm app, pages, widgets, features, entities và shared. Không phải dự án nào cũng cần đủ mọi layer ngay từ đầu, nhưng hiểu vai trò từng tầng sẽ giúp mở rộng codebase có kiểm soát.
Layer app và pages
Layer app thường chứa cấu hình cấp ứng dụng như router, provider, theme, store gốc, layout tổng thể hoặc thiết lập môi trường. Đây là nơi khởi tạo ứng dụng, không nên nhồi logic nghiệp vụ của từng màn hình.
Layer pages đại diện cho các trang hoặc route cụ thể. Một page có thể ghép widget, feature và entity để tạo thành trải nghiệm hoàn chỉnh, ví dụ trang giỏ hàng dùng widget tóm tắt đơn, feature áp mã giảm giá và entity cart.
Layer widgets, features và entities

Widgets là các khối giao diện lớn có ý nghĩa trên trang, chẳng hạn header, sidebar, product-list hoặc checkout-summary. Widgets thường ghép nhiều phần nhỏ hơn để tạo thành một khối UI có thể tái sử dụng trong một số ngữ cảnh.
Features là nơi đặt hành động mà người dùng có thể thực hiện. Trong Feature sliced, login, add-to-cart, search-product, update-profile hoặc apply-coupon đều có thể là feature. Một feature có thể bao gồm UI, state, validation, API và logic xử lý liên quan.
Entities mô tả các thực thể nghiệp vụ như user, product, order, article, comment hoặc invoice. Đây là nơi chứa model, type, hàm chuyển đổi dữ liệu, UI nhỏ gắn với thực thể và logic cốt lõi ít phụ thuộc vào màn hình cụ thể.
Layer shared và segment
Shared chứa phần dùng chung không phụ thuộc nghiệp vụ cụ thể, ví dụ UI kit, helper kỹ thuật, cấu hình HTTP client, constant chung hoặc hàm format ngày tháng. Khi dùng Feature sliced, shared cần được kiểm soát kỹ để không biến thành thư mục utils khổng lồ.
Segment là cách chia nhỏ bên trong một slice. Các segment thường gặp gồm ui, model, api, lib, config và types. Ví dụ feature login có thể có ui chứa form, model chứa trạng thái submit, api chứa hàm gọi endpoint và types chứa kiểu dữ liệu riêng.
Một ví dụ rút gọn có thể như sau:
- app/providers: cấu hình provider toàn ứng dụng
- pages/catalog: trang danh mục sản phẩm
- widgets/product-list: khối danh sách sản phẩm
- features/search-product: chức năng tìm kiếm
- entities/product: model và UI nhỏ của sản phẩm
- shared/ui: button, input, modal dùng chung
Lợi ích khi áp dụng Feature sliced cho dự án lớn

Lợi ích đầu tiên của Feature sliced là giảm sự mơ hồ khi đặt file. Thay vì hỏi “đưa tạm vào components hay utils?”, lập trình viên sẽ nhìn vào vai trò của code để chọn layer và slice phù hợp. Điều này giúp cấu trúc dự án phản ánh sản phẩm tốt hơn.
Lợi ích thứ hai là kiểm soát phụ thuộc. FSD khuyến khích code ở tầng cao dùng tầng thấp hơn, nhưng không import ngược tùy tiện. Quy tắc này giúp hạn chế vòng lặp phụ thuộc, giảm lỗi khó đoán và làm cho module ổn định hơn khi dự án mở rộng.
Lợi ích thứ ba của Feature sliced là hỗ trợ làm việc nhóm. Mỗi người có thể phụ trách một slice hoặc một nhóm feature mà ít va chạm với phần còn lại. Khi review code, reviewer cũng dễ phát hiện logic đặt sai tầng hoặc import phá vỡ ranh giới kiến trúc.
Lợi ích thứ tư là tái sử dụng có kiểm soát. Không phải đoạn code nào giống nhau cũng nên đưa ngay vào shared, vì nhiều logic chỉ giống tạm thời nhưng khác nghiệp vụ.
Cuối cùng, phương pháp này giúp onboarding nhanh hơn. Người mới có thể đi từ pages để hiểu màn hình, xuống widgets để hiểu khối giao diện, rồi vào features và entities để nắm nghiệp vụ.
So sánh Feature sliced với kiến trúc khác
So với cách chia theo loại file truyền thống, Feature sliced phù hợp hơn với dự án nhiều nghiệp vụ. Cách chia components, hooks, services và store rất dễ bắt đầu, nhưng càng lớn càng khó biết một file đang phục vụ phần nào của sản phẩm.
So với Atomic Design, FSD tập trung rộng hơn vào kiến trúc ứng dụng. Atomic Design mạnh khi xây dựng design system, nhưng không trả lời đầy đủ câu hỏi state, API, validation và logic nghiệp vụ nên nằm ở đâu.
So với Clean Architecture, Feature sliced gần với frontend thực tế hơn. Clean Architecture nhấn mạnh domain, use case và dependency inversion chặt chẽ. FSD nhẹ hơn, bám sát page, UI và hành vi người dùng nên dễ áp dụng trong nhiều đội frontend.
Khi nào nên áp dụng Feature sliced?
Bạn nên cân nhắc Feature sliced khi dự án có nhiều màn hình, nhiều luồng nghiệp vụ, nhiều developer cùng làm hoặc cần bảo trì trong thời gian dài. Dấu hiệu nên áp dụng gồm component bị dùng sai ngữ cảnh, store global phình to, API lẫn lộn và helper trùng lặp.
Nếu dự án đã tồn tại, không nên refactor toàn bộ trong một lần. Hãy bắt đầu từ một tính năng mới hoặc một khu vực đang gây đau đầu nhất, sau đó dần dần chuẩn hóa các phần khác. Cách này ít rủi ro và giúp đội ngũ học kiến trúc qua thực tế.
Cách bắt đầu với Feature sliced trong dự án
Bước đầu tiên khi dùng Feature sliced là thống nhất quy tắc import. Hãy xác định layer nào được import layer nào, phần nào public qua index file và phần nào chỉ dùng nội bộ trong slice. Nếu bỏ qua bước này, dự án có thể có thư mục đẹp nhưng phụ thuộc vẫn rối.
Bước thứ hai là định nghĩa rõ vai trò của shared. Chỉ đưa vào shared những thứ thật sự không phụ thuộc nghiệp vụ, chẳng hạn button, modal, input, hàm format hoặc client HTTP. Logic đơn hàng, quyền người dùng, trạng thái sản phẩm nên nằm trong feature hoặc entity tương ứng.
Bước thứ ba là đặt tên slice theo ngôn ngữ sản phẩm. Thay vì đặt tên quá kỹ thuật như form-handler hoặc data-service, hãy dùng login, checkout, add-to-cart, user-profile hoặc product-search. Khi tên thư mục gần với cách team nói về sản phẩm, code sẽ dễ hiểu hơn.
Bước thứ tư là áp dụng dần bằng convention và review. Có thể dùng alias import, eslint rule hoặc tài liệu nội bộ để giữ kỷ luật. Công cụ chỉ hỗ trợ; điều quan trọng là cả team hiểu vì sao cần ranh giới giữa các layer.
Ví dụ áp dụng Feature sliced trong React hoặc Vue
Giả sử bạn xây dựng trang thương mại điện tử. Với cấu trúc cũ, ProductCard, productApi, cartStore và useProduct có thể nằm ở nhiều thư mục khác nhau. Khi thêm wishlist hoặc checkout, lập trình viên phải mở nhiều nơi mới hiểu một luồng nghiệp vụ.
Với Feature sliced, bạn có thể đặt entities/product cho dữ liệu sản phẩm, entities/cart cho giỏ hàng, features/add-to-cart cho hành động thêm sản phẩm, features/apply-coupon cho mã giảm giá, widgets/product-list cho khối danh sách và pages/catalog cho trang danh mục.
Trong React, segment ui có thể chứa component JSX, model chứa state hoặc hook, api chứa hàm gọi server và types chứa TypeScript type. Trong Vue, ui có thể là component.vue, còn model có thể dùng Pinia hoặc composable.
Lưu ý để tránh áp dụng sai
Sai lầm phổ biến là tạo quá nhiều thư mục khi dự án chưa cần. Nếu một tính năng còn nhỏ, bạn không nhất thiết phải có đủ ui, model, api, lib và types. Hãy để cấu trúc phát triển theo nhu cầu thật, tránh sinh file rỗng.
Ngoài ra, không nên hiểu feature là một màn hình. Login là feature, còn LoginPage là page. Add-to-cart là feature, còn ProductDetailPage là page. Phân biệt đúng khái niệm này giúp code không bị lệch tầng ngay từ đầu.
Hiểu rõ Feature sliced sẽ giúp bạn đưa ra quyết định an toàn và phù hợp hơn trong thực tế.
Kết luận
Feature sliced là một cách tiếp cận thực dụng để tổ chức code frontend hiện đại. Bằng việc chia ứng dụng theo layer, slice và segment, đội ngũ có thể giảm rối thư mục, kiểm soát phụ thuộc, bảo trì dễ hơn và mở rộng sản phẩm bền vững hơn tại Lopy.
Điều quan trọng là không áp dụng máy móc. Với dự án nhỏ, bạn có thể dùng một phần. Với dự án lớn, hãy thống nhất quy ước, viết tài liệu nội bộ và kiểm tra qua review code. Khi triển khai đúng mức, Feature sliced giúp codebase frontend rõ ràng hơn, dễ cộng tác hơn và ít phát sinh nợ kỹ thuật hơn.
