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

Что должно быть в features в контексте FSD?

1.0 Junior🔥 181 комментариев
#Архитектура и паттерны

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

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

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

Features в FSD (Feature Sliced Design)

FSD — это методология архитектуры, которая организует код по функциональным слайсам. Папка features/ содержит самостоятельные, переиспользуемые функциональные модули, каждый из которых отвечает за одну пользовательскую возможность.

Что должно быть в features

Features — это набор функций, которые пользователь может взаимодействовать. Каждый feature — это независимый модуль с полным набором слоев архитектуры.

Структура одного feature

features/
├── auth/                    # Feature: аутентификация
│   ├── ui/                  # UI компоненты (представление)
│   │   ├── LoginForm.tsx
│   │   └── LoginForm.test.tsx
│   ├── model/               # Бизнес-логика и состояние
│   │   ├── authSlice.ts
│   │   ├── selectors.ts
│   │   └── types.ts
│   ├── api/                 # Взаимодействие с backend
│   │   └── loginAPI.ts
│   ├── lib/                 # Утилиты feature-специфичные
│   │   └── validateEmail.ts
│   └── index.ts             # Public API feature
│
├── comments/                # Feature: комментарии
│   ├── ui/
│   │   ├── CommentList.tsx
│   │   ├── CommentItem.tsx
│   │   └── CommentForm.tsx
│   ├── model/
│   │   ├── commentsSlice.ts
│   │   ├── selectors.ts
│   │   └── types.ts
│   ├── api/
│   │   └── commentsAPI.ts
│   └── index.ts
│
└── notifications/           # Feature: уведомления
    ├── ui/
    │   └── NotificationToast.tsx
    ├── model/
    │   └── notificationsSlice.ts
    └── index.ts

Слои внутри feature

1. UI слой — компоненты для отображения

  • Чистые, переиспользуемые компоненты React
  • Принимают данные и callbacks через props
  • Не зависят от Redux/состояния
// ui/LoginForm.tsx
export const LoginForm: React.FC<LoginFormProps> = ({ onSubmit, isLoading }) => {
  const [email, setEmail] = useState();
  // ...
  return <form>...</form>;
};

2. Model слой — управление состоянием

  • Redux slices, store configuration
  • Селекторы для доступа к состоянию
  • Типы (interfaces, types)
// model/authSlice.ts
const authSlice = createSlice({
  name: auth,
  initialState: { user: null, loading: false },
  reducers: { /* ... */ },
});

export const selectUser = (state) => state.auth.user;

3. API слой — запросы к серверу

  • Функции для HTTP запросов
  • Трансформация данных
  • Обработка ошибок
// api/loginAPI.ts
export const loginAPI = async (email: string, password: string) => {
  const response = await fetch(/api/v1/auth/login, {
    method: POST,
    body: JSON.stringify({ email, password }),
  });
  return response.json();
};

4. Lib слой — вспомогательные утилиты

  • Функции-helpers
  • Валидация
  • Трансформация данных (не API)
// lib/validateEmail.ts
export const isValidEmail = (email: string): boolean => {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
};

5. Index (Public API) — экспорт для остального кода

// index.ts
export { LoginForm } from ./ui;
export { authSlice, selectUser } from ./model;
export { loginAPI } from ./api;
export { isValidEmail } from ./lib;

Правила использования features

1. Иерархия зависимостей:

ui → model → api → lib

UI может использовать model, api и lib. Model может использовать api и lib. API только использует lib.

2. Изоляция features Features не должны импортировать друг друга напрямую:

// ❌ Плохо
import { LoginForm } from @/features/auth;
// ✅ Хорошо — использовать через index.ts
import { LoginForm } from @/features/auth;

3. Переиспользуемость Feature должен быть независимым модулем, который можно использовать в разных местах приложения.

Что НЕ должно быть в features

  • Глобальное состояние приложения (в store/)
  • Макеты страниц (в pages/)
  • Переиспользуемые компоненты без бизнес-логики (в shared/)
  • Конфигурация приложения (в app/)

Пример использования feature

// pages/login.tsx
import { LoginForm, loginAPI } from @/features/auth;
import { useAppDispatch } from @/store;

export default function LoginPage() {
  const dispatch = useAppDispatch();

  const handleLogin = async (email: string, password: string) => {
    try {
      const result = await loginAPI(email, password);
      dispatch(setUser(result.user));
    } catch (error) {
      // обработка ошибки
    }
  };

  return <LoginForm onSubmit={handleLogin} />;
}

Преимущества FSD для features

  • Модульность — легко добавлять/удалять функции
  • Переиспользуемость — один feature можно использовать в разных модулях
  • Масштабируемость — при росте проекта структура остаётся понятной
  • Тестирование — каждый feature можно тестировать независимо
  • Командная работа — разные разработчики могут работать на разных features без конфликтов