Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
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
- Масштабируемость: легко добавлять новые фичи
- Изоляция: фичи независимы друг от друга
- Переиспользование: ясно, что можно переиспользовать
- Командная работа: разные разработчики работают на разных фичах
- Поддержка: легко находить и понимать код
- Тестирование: каждая фича легко тестируется изолированно
Недостатки FSD
- Сложнее для маленьких проектов (при 10 файлов это overengineering)
- Кривая обучения: нужно понимать архитектуру
- Может быть многословно: много файлов и папок
Когда использовать FSD
- Проект среднего и большого размера (100+ компонентов)
- Долгосрочный проект
- Команда разработчиков
- Нужна высокая масштабируемость
Когда FSD оverkill
- Маленький проект (< 10 компонентов)
- MVP или прототип
- Один разработчик, короткий временной промежуток