Как я раскладываю React-проект под реальную боевую задачу
Учебные туториалы по React часто заканчиваются на src/App.jsx и куче компонентов в одной папке. В бою такое быстро превращается в кашу. Расскажу, как я обычно собираю структуру фронта, чтобы через полгода не хотелось всё выкинуть.
Базовая структура проекта
Обычно стартую с чего-то такого:
src/ ├ app/ │ ├ App.tsx │ ├ providers/ │ └ routes/ ├ entities/ ├ features/ ├ widgets/ ├ pages/ └ shared/ ├ ui/ ├ lib/ ├ config/ └ api/
Коротко: • app/ — точка входа, роутинг, провайдеры (Router, Store, i18n и т.п.). • pages/ — страницы как композиция виджетов/фич. • widgets/ — крупные блоки страницы (шапка, боковое меню, лента товаров). • features/ — законченные пользовательские действия (логин, смена пароля, фильтр каталога). • entities/ — бизнес-сущности (User, Product, Order) + их отображение. • shared/ — переиспользуемые части без бизнес-логики.
Такой подход близок к Feature-Sliced, но без фанатизма: можно адаптировать под размер проекта.
Как я описываю сущности
Пример для товара:
entities/product/ model/ types.ts hooks.ts ui/ ProductCard/ ProductPrice/
• в model/ лежат типы, хуки, селекторы; • в ui/ — dumb-компоненты, которые можно переиспользовать.
Важно: сущность не знает про конкретные страницы; наоборот, страницы собирают сущности.
Фичи: «маленькие законченные истории»
Примеры фич: • add-to-cart • change-password • products-filter • edit-profile
Структура:
features/add-to-cart/ model/ ui/
Внутри: • хук useAddToCart, • кнопка AddToCartButton, • возможно, модалка подтверждения.
Если нужно переехать на другое API — меняю model, UI почти не трогаю.
Что я кладу в shared • shared/ui — кнопки, инпуты, модалки, типовые таблицы. • shared/lib — утилиты (formatDate, debounce, validators). • shared/api — базовый клиент (axiosInstance), интерсепторы. • shared/config — константы, feature-флаги, env-настройки.
Правило: shared не должен знать о бизнес-сущностях типа Order или Product.
Организация роутов
Пример:
// app/routes/index.tsx import { MainPage } from "@/pages/main"; import { ProductPage } from "@/pages/product";
export const routes = [ { path: "/", element: }, { path: "/product/:id", element: }, ];
Внутри страницы:
// pages/product/ui/ProductPage.tsx export const ProductPage = () => (
);
Роуты знают только о pages, а не о конкретных фичах.
Типичные ошибки, которые я вижу • Все компоненты в одной папке components/. • Смешение API-вызовов, верстки и бизнес-логики в одном файле. • Глобальный store с десятками несвязанных сущностей. • Шеринг всего подряд через shared/, который превращается в свалку.
Чек-лист при старте React-проекта • Структура разложена по слоям: app / pages / widgets / features / entities / shared. • Бизнес-сущности выделены в entities с model и ui. • Пользовательские действия собраны в features. • Роуты завязаны на pages, а не на отдельные компоненты. • В shared лежат только переиспользуемые вещи без бизнес-логики. • Есть понятные правила импорта (например, только «вверх» по слоям).
Итог
Сама по себе структура не ускорит сайт и не решит все баги, но она задаёт рамки: куда класть код, как переиспользовать сущности и фичи, как не утонуть в хаосе через полгода.
· 15.11.2025
Поскорее описание структуры папок очень плохо читается не как будто всё на верхнем слое лежит. Разложил бы через ASCII, было б легче читать. А, и попробуй блоки кода через … оформить. Тут, вроде md ограниченно поддерживается.
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
коммент удалён
· 15.11.2025
Я настроил автопостинг из тг, так криво перенеслось. Спасибо, сейчас поправлю
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
ответ удалён