Структура проекта (Frontend)

Рекомендуемая файловая структура для React/TypeScript-проекта на Vite — scalable, без over-engineering.

Задача

Где положить компоненты, хуки, типы, API-клиент? Нужна структура, которая легко масштабируется и понятна любому разработчику с первого взгляда.

Решение

project/
├── public/                  # статика (favicon, robots.txt, OG-изображения)
│
├── src/
│   ├── assets/              # шрифты, иконки, фоновые изображения
│   │
│   ├── components/          # переиспользуемые UI-компоненты
│   │   ├── Button/
│   │   │   ├── Button.tsx
│   │   │   ├── Button.module.css
│   │   │   └── index.ts     # реэкспорт
│   │   ├── Modal/
│   │   └── ...
│   │
│   ├── pages/               # компоненты-страницы (роутинг)
│   │   ├── Home/
│   │   ├── Dashboard/
│   │   └── ...
│   │
│   ├── features/            # фичи (feature-sliced подход)
│   │   ├── auth/            # авторизация
│   │   │   ├── components/
│   │   │   ├── hooks/
│   │   │   └── api.ts
│   │   └── cart/
│   │
│   ├── hooks/               # глобальные кастомные хуки
│   │   ├── useFetch.ts
│   │   ├── useLocalStorage.ts
│   │   └── useWindowSize.ts
│   │
│   ├── api/                 # API-клиент и запросы
│   │   ├── client.ts        # базовый fetchJSON / axios instance
│   │   ├── users.ts         # запросы: getUsers, createUser...
│   │   └── products.ts
│   │
│   ├── store/               # глобальное состояние (Zustand, Redux, Context)
│   │   └── index.ts
│   │
│   ├── types/               # общие TypeScript-типы
│   │   ├── api.ts           # типы ответов API
│   │   └── index.ts
│   │
│   ├── utils/               # чистые утилиты
│   │   ├── debounce.ts
│   │   ├── formatDate.ts
│   │   └── storage.ts
│   │
│   ├── styles/              # глобальные стили
│   │   ├── global.css
│   │   └── variables.css
│   │
│   ├── App.tsx
│   └── main.tsx
│
├── .env.example
├── .gitignore
├── .editorconfig
├── eslint.config.js
├── .prettierrc
├── tsconfig.json
├── vite.config.ts
└── package.json

Алиас @/ в tsconfig.json и vite.config.ts:

// Вместо: import { Button } from '../../components/Button'
// Пиши:   import { Button } from '@/components/Button'

Ключевые моменты

  • Компонент как папка (Button/Button.tsx + index.ts) — позволяет добавить тесты, стили, типы рядом не засоряя корень.
  • features/ — группировка по доменному смыслу (auth, cart, user) лучше масштабируется, чем плоские components/.
  • api/ отдельно от hooks/ — API-функции (запросы) и React-хуки (useFetch) разделены по ответственности.
  • utils/ — только чистые функции без React-зависимостей; тестируются изолированно.

Варианты

  • Feature-Sliced Design (FSD) — более строгая методология: app/, pages/, widgets/, features/, entities/, shared/.
  • Для маленьких проектов (< 10 компонентов) — упрости до components/, hooks/, utils/, pages/.

Связанные рецепты / темы