← Назад к вопросам

В чем идеология FSD?

1.7 Middle🔥 171 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

FSD: Feature-Sliced Design - идеология и архитектура

FSD (Feature-Sliced Design) — это методология для структурирования больших и масштабируемых фронтенд-приложений. Это не фреймворк, а архитектурный подход, разработанный русскими разработчиками для решения проблем в организации кода в реальных проектах.

Основная идеология FSD

Gлавная идея: разделить приложение по слоям и фичам, а не по типам файлов (как в классической структуре: components/, pages/, utils/).

Классический подход (BAD):

project/
  components/        <- Все компоненты в одной папке
    Button.tsx
    Header.tsx
    UserCard.tsx
  pages/            <- Все страницы вместе
    Home.tsx
    Profile.tsx
  utils/            <- Все утилиты вместе
    helpers.ts
    validators.ts

Проблемы:

  • Со временем папки становятся огромными (200+ файлов)
  • Сложно найти, что относится к конкретной фиче
  • Зависимости между компонентами запутаны
  • Реиспользование кода затруднено

FSD подход (GOOD):

project/
  features/         <- Независимые фичи
    Auth/
      ui/
      model/
      api/
    Comments/
      ui/
      model/
      api/
  entities/         <- Доменные сущности
    User/
    Post/
  shared/          <- Общий код для всего приложения

Слои FSD (от нижнего к верхнему)

Важно: зависимости только идут вниз, не вверх!

Визуально:

    Presentation
         ↓
    Features
         ↓
    Entities
         ↓
    Shared

1. Shared (общий слой)

Это низший слой. Он содержит переиспользуемый код, который не знает о домене приложения:

// shared/ui/Button.tsx
export function Button({ children, onClick }: ButtonProps) {
  return <button onClick={onClick}>{children}</button>;
}

// shared/lib/formatDate.ts
export const formatDate = (date: Date) => {...};

// shared/constants/api.ts
export const API_URL = 'https://api.example.com';

Что может быть в Shared:

  • UI компоненты (Button, Input, Modal)
  • Утилиты (helpers, validators)
  • Константы
  • Хуки (useMediaQuery, useDebounce)
  • Типы общего назначения

2. Entities (сущности)

Это доменные модели приложения. Сущности не зависят друг от друга:

// entities/User/
//   api/         <- API для User
//   model/       <- User модель и логика
//   ui/          <- User компоненты

// entities/User/model/types.ts
export interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user';
}

// entities/User/ui/UserCard.tsx
import { User } from '../model/types';
export function UserCard({ user }: { user: User }) {
  return (
    <div>
      <h3>{user.name}</h3>
      <p>{user.email}</p>
    </div>
  );
}

Примеры сущностей:

  • User (пользователь)
  • Post (пост)
  • Comment (комментарий)
  • Product (товар)

3. Features (фичи)

Это слой пользовательских действий и взаимодействий. Фичи используют сущности, но НЕ зависят друг от друга:

// features/CreateComment/
//   api/         <- API для создания
//   model/       <- Логика создания
//   ui/          <- UI создания

// features/CreateComment/ui/CreateCommentForm.tsx
import { Comment } from 'entities/Comment';
import { createComment } from '../api/createCommentApi';

export function CreateCommentForm({ postId }: { postId: string }) {
  const [content, setContent] = useState('');

  const handleSubmit = async () => {
    await createComment({ postId, content });
  };

  return (
    <form onSubmit={handleSubmit}>
      <textarea value={content} onChange={e => setContent(e.target.value)} />
      <button type="submit">Создать</button>
    </form>
  );
}

Примеры фич:

  • AuthForm (авторизация)
  • CommentCreation (создание комментария)
  • LikeButton (лайк поста)
  • NotificationCenter (центр уведомлений)

4. Widgets (опционально)

Это сложные UI-компоненты, которые комбинируют несколько фич:

// widgets/PostCard/
//   ui/PostCard.tsx

import { Post } from 'entities/Post';
import { LikeButton } from 'features/LikePost';
import { CreateComment } from 'features/CreateComment';

export function PostCard({ post }: { post: Post }) {
  return (
    <div>
      <h2>{post.title}</h2>
      <p>{post.content}</p>
      <LikeButton postId={post.id} />
      <CreateComment postId={post.id} />
    </div>
  );
}

5. Pages (страницы)

Это главные компоненты приложения (в Next.js это app/ или pages/):

// pages/posts/[id]/page.tsx
import { PostCard } from 'widgets/PostCard';
import { getPost } from 'entities/Post/api';

export default async function PostPage({ params }: { params: { id: string } }) {
  const post = await getPost(params.id);
  return <PostCard post={post} />;
}

6. App (приложение)

Это корневая конфигурация: маршруты, контекст, глобальные провайдеры:

// app/layout.tsx
import { AuthProvider } from 'app/providers/AuthProvider';
import { Router } from 'app/router';

export default function RootLayout() {
  return (
    <AuthProvider>
      <Router />
    </AuthProvider>
  );
}

Полная структура FSD проекта

project/
  app/                      <- Корневая конфигурация
    providers/
      AuthProvider.tsx
    router/
      routes.ts
    layout.tsx

  pages/                    <- Страницы приложения
    Home/
      page.tsx
    Profile/
      page.tsx

  widgets/                  <- Сложные UI компоненты
    PostCard/
      ui/
      model/
    Header/
      ui/

  features/                 <- Пользовательские фичи
    CreateComment/
      api/
      model/
      ui/
    LikePost/
      api/
      ui/
    Auth/
      api/
      model/
      ui/

  entities/                 <- Доменные сущности
    User/
      api/
      model/
      ui/
    Post/
      api/
      model/
      ui/
    Comment/
      model/
      ui/

  shared/                   <- Общий код
    ui/
      Button/
      Input/
    lib/
      formatters/
      validators/
    constants/
    types/

Правило зависимостей: слайсы изолированы

ОЧЕНЬ ВАЖНО: фичи НЕ должны зависеть друг от друга!

// features/CreateComment/ui/CreateCommentForm.tsx

// МОЖНО - зависит от нижних слоев
import { Comment } from 'entities/Comment';
import { createCommentApi } from '../api';
import { Button } from 'shared/ui';

// ЗАПРЕЩЕНО - зависит от другой фичи!
import { LikeButton } from 'features/LikePost'; // ERROR!

// ЗАПРЕЩЕНО - зависит от верхних слоев
import { PostPage } from 'pages/Post'; // ERROR!

Структура слайса (фичи или сущности)

Каждый слайс имеет стандартную структуру:

features/CreateComment/
  ├── api/              <- API запросы
  │   ├── createCommentApi.ts
  │   └── types.ts
  ├── model/            <- Логика и состояние
  │   ├── types.ts
  │   ├── useCommentForm.ts (hook)
  │   └── store.ts      <- если используется Redux
  ├── ui/               <- React компоненты
  │   ├── CreateCommentForm.tsx
  │   └── index.ts      <- public API
  └── index.ts          <- главный экспорт

index.ts — это публичный API слайса:

// features/CreateComment/index.ts
export { CreateCommentForm } from './ui/CreateCommentForm';
export type { CreateCommentInput } from './api/types';

Так другие слайсы импортируют только необходимое:

import { CreateCommentForm } from 'features/CreateComment';
// Не нужно знать внутреннюю структуру

Преимущества FSD

  1. Масштабируемость: легко добавлять новые фичи
  2. Изоляция: фичи независимы друг от друга
  3. Переиспользование: ясно, что можно переиспользовать
  4. Командная работа: разные разработчики работают на разных фичах
  5. Поддержка: легко находить и понимать код
  6. Тестирование: каждая фича легко тестируется изолированно

Недостатки FSD

  1. Сложнее для маленьких проектов (при 10 файлов это overengineering)
  2. Кривая обучения: нужно понимать архитектуру
  3. Может быть многословно: много файлов и папок

Когда использовать FSD

  • Проект среднего и большого размера (100+ компонентов)
  • Долгосрочный проект
  • Команда разработчиков
  • Нужна высокая масштабируемость

Когда FSD оverkill

  • Маленький проект (< 10 компонентов)
  • MVP или прототип
  • Один разработчик, короткий временной промежуток
В чем идеология FSD? | PrepBro