Перейти к содержанию
Innovialabs

Feature-Sliced Design: архитектура фронтенда для больших проектов

Продвинутое4 мин

Коротко

Feature-Sliced Design делит фронтенд на слои по уровню ответственности, слои — на слайсы по бизнес-доменам, а слайсы — на технические сегменты; модуль может импортировать только из нижележащих слоёв и только через публичный API слайса.

Что такое Feature-Sliced Design

Feature-Sliced Design (FSD) — методология, которая структурирует фронтенд-код по бизнес-смыслу, а не по типу файлов. Вместо одной огромной папки components/ и hooks/ код группируется в слои, слайсы и сегменты с одним строгим правилом: зависимости направлены только вниз. В результате фичу можно найти, изменить или удалить, не сломав несвязанные части.

Слои

Слои — папки верхнего уровня, от самых конкретных к самым общим:

СлойНазначениеПример
appИнициализация: провайдеры, роутинг, глобальные стилиПровайдер темы, настройка стора
pagesЦелые страницы, собранные из нижних слоёвСтраница товара, профиль
widgetsКрупные самостоятельные блоки интерфейсаШапка, список товаров с фильтрами
featuresДействия пользователя, несущие бизнес-ценностьДобавить в корзину, войти, оставить отзыв
entitiesБизнес-сущностиПользователь, товар, заказ
sharedПереиспользуемый код без бизнес-логикиUI-кит, API-клиент, утилиты

В старой документации упоминается слой processes — он устарел, а его логика обычно переезжает в features или app. Все слои не обязательны: небольшие проекты часто обходятся app, pages, shared и парой сущностей.

Слайсы и сегменты

Слайсы делят слой по бизнес-доменам: entities/user, entities/product, features/add-to-cart. У слоёв app и shared слайсов нет.

Сегменты делят слайс по техническому назначению. Типичные названия:

  • ui — компоненты
  • model — состояние, сторы, бизнес-логика
  • api — запросы к бэкенду
  • lib — вспомогательный код этого слайса
  • config — константы и флаги

Правила импорта и публичный API

FSD держится на двух правилах:

  1. Модуль импортирует только из слоёв строго ниже. Фича может использовать entities и shared, но не widgets и не другую фичу. Слайсы одного слоя друг друга не импортируют.
  2. У каждого слайса есть публичный API — файл index.ts. Остальной код импортирует только из него, никогда из внутренних путей.
// entities/product/index.ts
export { ProductCard } from "./ui/product-card";
export { useProduct } from "./model/use-product";
export type { Product } from "./model/types";
// правильно
import { ProductCard } from "@/entities/product";
// неправильно: лезем во внутренности
import { ProductCard } from "@/entities/product/ui/product-card";

Линтер Steiger и ESLint-плагины для границ модулей проверяют эти правила автоматически, и архитектура не зависит только от код-ревью.

Если две сущности действительно нужны друг другу (заказ ссылается на пользователя), FSD предлагает нотацию кросс-импорта через @x — явное, контролируемое исключение. Используйте её редко.

Пример структуры на Next.js

Папка app/ в Next.js совпадает по имени со слоем app в FSD. Распространённое решение: оставить роутинг Next.js в корневой app/ в виде тонких файлов, которые реэкспортируют FSD-страницы, а код FSD перенести в src/.

app/                      # только роутинг Next.js
  products/[id]/page.tsx  # export { ProductPage as default } from "@/pages/product"
src/
  app/                    # провайдеры, глобальные стили
  pages/
    product/
      ui/product-page.tsx
      index.ts
  widgets/
    product-gallery/
  features/
    add-to-cart/
      ui/add-to-cart-button.tsx
      model/use-add-to-cart.ts
      index.ts
  entities/
    product/
      api/get-product.ts
      ui/product-card.tsx
      model/types.ts
      index.ts
  shared/
    ui/button.tsx
    api/http.ts

Осторожнее и с именем pages: Next.js может воспринять папку pages (в том числе src/pages) как маршруты Pages Router. В официальном руководстве FSD по Next.js описано, как избежать конфликта, — сверьтесь с ним, прежде чем фиксировать структуру.

Миграция существующего проекта

Не переписывайте всё разом. Постепенный путь:

  1. Создайте shared и перенесите туда UI-кит, API-клиент и утилиты.
  2. Выделите главные сущности, о которых говорит приложение (пользователь, товар, заказ).
  3. Затем перенесите страницы и держите их тонкими: они собирают, а не содержат логику.
  4. Выделяйте фичи по мере того, как трогаете код в новых задачах.
  5. Когда структура устоится, включите линтинг правил импорта и исправляйте нарушения постепенно.

Самая частая сложность — понять, что фича, а что сущность. Практический тест: сущность — существительное (товар), фича — глагол, действие пользователя (добавить товар в корзину).

Когда FSD избыточен

  • Лендинги, небольшие маркетинговые сайты и прототипы.
  • Короткоживущие MVP, где скорость важнее структуры.
  • Один разработчик и небольшое приложение на несколько экранов.
  • Команды, которые не будут соблюдать правила: наполовину внедрённый FSD хуже простой, но последовательной структуры.

FSD окупается на проектах с несколькими разработчиками, множеством фич и долгой жизнью.

Частые вопросы

Нет. Методология не привязана к фреймворку и применяется с Vue, Svelte, Angular и другими. Слои и правила импорта остаются теми же.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.