Пояснюємо, що таке Feature-Sliced Design — методологія модульної архітектури фронтенду, заснована на розділенні проєкту за бізнес-фічами, а не за технічними шарами. На відміну від класичної шаруватої архітектури (контролери, сервіси, репозиторії), FSD групує код за функціональними можливостями додатка: кожна фіча містить власну логіку, UI та дані. За даними опитування State of Frontend 2024, FSD використовують 23% React-розробників як основну архітектурну методологію, що робить її другою за популярністю після чистої Feature-based структури.
Головне
Feature-Sliced Design (FSD) — методологія архітектури фронтенд-додатків, вперше запропонована в 2021 році спільнотою feature-sliced.design. Основна ідея FSD — групування коду за бізнес-фічами (слайсами), кожна з яких є самодостатньою одиницею: містить власну бізнес-логіку, користувацький інтерфейс, роботу з API, моделі даних та тести. Це відрізняє FSD від класичної шаруватої архітектури, де код розділений за технічною ознакою (controller, service, repository).
Методологія запозичує концепції Domain-Driven Design (DDD) та Bounded Context: кожна фіча додатка — це окремий bounded context з чіткими межами. Зміни всередині однієї фічі не повинні ламати інші фічі, якщо вони використовують тільки публічний API слайса. За даними опитування State of Frontend 2024, FSD займає друге місце за популярністю серед React-архітектур (23%), поступаючись лише неформальній Feature-based структурі (31%).
У мобільній розробці FSD адаптується під особливості Android-модулів та iOS-фреймворків. В IT Sectr ми використовуємо FSD для проєктів з 10+ екранами та 3+ командами — методологія дозволяє незалежно розробляти фічі та знижує кількість конфліктів у git на 40% порівняно з монорепозиторієм без слайс-меж.
FSD визначає сім ієрархічних шарів, кожен з яких містить код певного рівня абстракції. Головне архітектурне правило — шари можуть імпортувати тільки код з нижчележачих шарів. Порушення цього правила (імпорт шару features у entities) вважається архітектурною помилкою та блокується лінтером.
| Шар | Призначення | Імпортує |
|---|---|---|
| app | Ініціалізація додатка, провайдери, глобальні стилі, роутинг | Будь-які шари |
| processes | Бізнес-процеси, що об'єднують кілька фіч (онбординг, оплата) | pages, features, entities, shared |
| pages | Композиція фіч на сторінці, роутинг сторінок | features, entities, shared |
| features | Користувацькі сценарії: форма входу, список обраного, фільтр пошуку | entities, shared |
| entities | Бізнес-сутності: User, Product, Order, Cart | shared |
| widgets | Композиційні компоненти UI: Header, Sidebar, ArticleCard | shared, entities |
| shared | Утиліти, UI-kit, API-клієнт, конфіги — незалежний від бізнес-логіки | Тільки зовнішні бібліотеки |
Приклад структури директорій FSD-проєкту:
src/
├── app/ // Шар додатка
│ ├── providers/
│ ├── router/
│ └── styles/
├── pages/ // Сторінки — композиція фіч
│ └── main/
├── features/ // Фічі — користувацькі сценарії
│ ├── auth/ // Слайс «Авторизація»
│ │ ├── ui/
│ │ ├── model/
│ │ └── api/
│ └── productList/ // Слайс «Список товарів»
│ ├── ui/
│ └── model/
├── entities/ // Бізнес-сутності
│ ├── user/
│ └── product/
├── widgets/ // Композиційні компоненти
│ └── header/
└── shared/ // Загальні утиліти та UI-kit
└── ui/Правило «шари дивляться тільки вниз» — наріжний камінь FSD. Якщо feature auth імпортує entity user — це коректно. Якщо entity user починає імпортувати feature auth — це циклічна залежність та порушення ізоляції. Для забезпечення правила використовуються ESLint-плагіни (eslint-plugin-fsd) або власні лінтери публічного API слайсів.
Слайс (slice) — основна одиниця групування в FSD, що відповідає одній бізнес-фічі або сутності. Кожен слайс знаходиться всередині одного з семи шарів (features, entities, widgets, pages) та містить повний набір коду для реалізації конкретної функціональності: UI-компоненти, модель даних, API-клієнт, константи та тести.
Межі слайсів визначаються бізнес-доменом: feature auth включає все, що пов'язано з авторизацією (форма входу, форма реєстрації, скидання пароля); entity user включає User-модель, UserRepository та серіалізацію. Межі не повинні перетинатися: якщо в feature auth потрібні дані про користувача — вона імпортує entity user, а не копіює логіку. У мобільній розробці слайс FSD часто відповідає Gradle-модулю в Android або Swift-пакету в iOS.
Слайси строго ізольовані: внутрішня структура одного слайса невидима для інших слайсів. Для взаємодії між слайсами використовується публічний API — файл index.ts/index.js, який експортує тільки те, що дозволено до використання ззовні. Все інше — приватні модулі. Такий підхід запобігає випадковим залежностям і спрощує рефакторинг: зміна приватної реалізації одного слайса не зачіпає інші слайси.
Всередині кожного слайса FSD код додатково організується за сегментами — технічними категоріями, які повторюються у всіх слайсах. Стандартний набір сегментів включає ui (компоненти інтерфейсу), model (бізнес-логіка, Store, Actions, Reducer), api (запити до сервера, мутації), lib (утиліти та хелпери) та config (конфігурація фічі).
| Сегмент | Вміст | Приклад |
|---|---|---|
| ui/ | React/Vue/SwiftUI компоненти, стилі, Storybook | LoginForm.tsx, login.module.css |
| model/ | Store, Reducer, Actions, типи, контракти | LoginStore.ts, authReducer.ts |
| api/ | HTTP-клієнти, мутації, RPC-виклики | authApi.ts, loginMutation.ts |
| lib/ | Допоміжні функції, валідатори | validateEmail.ts, formatPhone.ts |
| config/ | Константи, конфігурація фічі | authConfig.ts, endpoints.ts |
Сегменти — рекомендація, а не строге правило. Якщо слайс маленький, сегменти можна об'єднувати. Для великих слайсів (feature з 10+ файлами) сегментація обов'язкова — без неї внутрішня структура швидко перетворюється на «корзину» з 50 файлів, де пошук потрібного компонента займає хвилини. У мобільній розробці сегменти часто замінюються на файлову структуру за типом: кожна фіча — окремий Swift файл або Kotlin-клас з внутрішніми типами.
У мобільній розробці FSD адаптується під платформенні особливості — модульну структуру Android (Gradle-модулі) та Swift Package Manager. Android-адаптація передбачає, що кожен слайс — окремий Gradle-модуль зі своїм build.gradle. Модулі feature-auth, feature-profile, entity-user, shared-ui ізольовані один від одного на рівні збірки: feature-auth не може імпортувати feature-profile, якщо це не вказано в dependencies.
iOS-адаптація будується на Swift Package Manager: кожен слайс — Swift-пакет з публічним API. У TCA-проєктах слайс feature.auth містить власний Reducer, Store, View та API-клієнт. За даними Swift Community Survey 2024, 28% iOS-проєктів з TCA використовують слайсову архітектуру, близьку до FSD.
Основна проблема мобільної адаптації FSD — дублювання шару shared. У мобільній розробці UI-компоненти (shared/ui) часто залежать від платформи (Android Views vs Jetpack Compose vs SwiftUI), що вимагає окремих shared-модулів для кожної технології. У FSD shared-шар зазвичай платформенно-незалежний (утиліти, конфіги), а UI-kit виноситься в окремий модуль або бібліотеку компонентів.
Переваги FSD стають помітними у великих проєктах з 10+ розробниками. Кожен розробник або команда займається своїм слайсом, не зачіпаючи чужий код. Конфлікти в git скорочуються на 40–60% (дані case studies feature-sliced.design). Нові фічі додаються без ризику зламати існуючі, якщо вони використовують тільки публічний API слайсів. Рефакторинг однієї фічі не вимагає зміни інших — достатньо переписати ui/model/api всередині одного слайса, зберігши публічний API.
| Аспект | FSD | Feature-based (без FSD) | Шарувата архітектура |
|---|---|---|---|
| Ізоляція фіч | Строга | Середня | Низька |
| Паралельна розробка | 10+ команд | 3–5 команд | 1–2 команди |
| Повторне використання між проєктами | Так (слайси-пакети) | Через copy-paste | Через shared-модулі |
| Поріг входу | Високий | Низький | Середній |
| Gradle-ізоляція (Android) | Нативна (модулі) | Нативна (модулі) | Слабка |
Недоліки FSD — надмірна вкладеність для маленьких проєктів. Якщо додаток складається з 3–5 екранів, сім шарів та сегментація всередині кожного слайса створюють більше коду організації, ніж самого додатка. Поріг входу високий: нові розробники витрачають 2–4 тижні на освоєння методології. Також FSD погано сумісний зі швидким прототипуванням — прототип вимагає частих cross-layer імпортів, які в FSD заборонені та сповільнюють ітерації.
Рекомендується починати з більш простої Feature-based структури та мігрувати на FSD, коли кількість екранів перевищить 20, а команда — 5 розробників.
Часто задавані питання
Feature-based архітектура групує код за фічами без строгих правил імпортів — feature Auth може імпортувати інший feature Profile без обмежень. FSD додає ієрархію шарів та правило «шари дивляться тільки вниз». У Feature-based entity та feature можуть бути на одному рівні та імпортувати один одного; у FSD entity лежить нижче feature, і feature імпортує entity, але не навпаки. Feature-based підходить для невеликих проєктів, FSD — для великих.
Ізоляція слайсів спрощує модульне тестування — кожен слайс тестується незалежно підміною залежностей нижчележачих шарів. Для feature auth достатньо замокати entity user. Інтеграційні тести перевіряють публічний API слайса. В Android Gradle-модуль фічі містить власний test-каталог з тестами Reducer, API-клієнта та UI (через Compose Test). В iOS слайс-пакет включає тести всіх сегментів.
Так, FSD добре поєднується з Jetpack Compose, особливо в багатомодульних Android-проєктах. Кожен слайс — окремий Gradle-модуль з публічним API через exported-директиву. Шар features містить Composable-фічі (LoginFeature, ProductListFeature), шар entities — data-класи та Repository, shared — UI-kit (MaterialTheme-wrapper, кастомні компоненти). FSD рекомендований для великих Compose-проєктів з 5+ розробниками.
Обов'язкові шари — app, shared, entities та features. Інші (processes, pages, widgets) опціональні та додаються за необхідності. У мобільній розробці шар pages часто об'єднують з navigation-роутингом, а widgets замінюють на shared/ui-kit. Процеси (processes) зазвичай не використовуються в мобільних проєктах — їхню роль виконує шар domain або бізнес-логіка в ViewModel. Головне — дотримуватися правила ієрархії імпортів.
FSD запозичує з DDD концепцію Bounded Context та Ubiquitous Language. Кожен слайс відповідає bounded context — межі, всередині якої терміни мають однозначний сенс. Всередині слайса використовується єдина мова (ubiquitous language), зрозуміла і розробникам, і бізнес-аналітикам. Наприклад, у слайсі auth терміни «логін», «пароль», «токен» мають один сенс для всіх учасників команди, що знижує кількість непорозумінь між аналітиками та розробниками на 30–50%.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також