Исследование структуры папок


Feature-first

Пример (приблизительный) структуры feature-first с чётким разделением ответственности между технической инфраструктурой, бизнес-логикой и пользовательским интерфейсом. Цель - обеспечить масштабируемость, поддерживаемость и низкую связанность.

Примечание: добавлена папка core, чтобы shared не превратился в «свалку».

Структура feature-first

core vs shared

Простое правило:

Если я удалю эту папку, сломается ли всё приложение?

  • Да core
  • Нет, но придётся переписать часть кода shared

Задаёт ли это способ разработки для фич?

  • Да core
  • Нет, это просто удобный инструмент shared

pages vs features

✅ Что pages/* МОЖЕТ содержать

  • Получение параметров маршрута (router.query, getServerSideProps)
  • Выбор layout
  • Компоновка компонентов
  • Передача props
  • Решение «какой экран отобразить»

❌ Что pages/* НЕ ДОЛЖЕН содержать

  • Бизнес-логика features
  • Прикладные хуки (use cases) features
  • Маппинг DTO → FormType features
  • Сложная оркестрация (workflow) features
  • Прямые вызовы React Query или слоя доступа к данным features

Внутренняя структура features/my-feature

Папка feature - это UI-модуль, ориентированный на бизнес, независимый от маршрутизации, который предоставляет связанные между собой строительные блоки для создания одной или нескольких страниц.

⚠️ Никакой зависимости от маршрутизации (без router.query) Должно передаваться через props из /pages

1. Screens

Точка входа бизнес-UI.


features/orders/
├── order-overview/
├── create-order/

Содержит:

  • UI-композицию, специфичную для бизнес-задачи
  • Вызовы прикладных хуков (контроллеров)

2. Components (чистый и переиспользуемый UI)


features/orders/
├── OrdersTable.tsx
├── OrderFilters.tsx

Содержит:

  • JSX
  • props
  • callbacks
  • без React Query
  • без бизнес-логики

❌ Что НЕ ДОЛЖНО быть в папке feature

  • Зеркальной структуры pages/: создаёт связанность с маршрутизацией
  • Прямого доступа к router: маршрутизация - это инфраструктура pages/
  • Глобальной логики layout: вне области ответственности feature
  • Глобальных providers: должны быть на уровне приложения

Управление layout

Ключевой принцип

Layout - это решение о композиции UI, а не о бизнес-логике.

Он описывает как отображается интерфейс, а не что происходит.

Типы layout и их размещение


1. Layout страницы (route)

  • Оборачивает всю страницу
  • Определяется маршрутизацией

📍 В pages/

  • Глобальный напрямую в _app.tsx, либо вынести UI в layouts/defaultLayout.tsx, если файл становится слишком большим и ухудшается читаемость
  • Общий контекстный shared/components/layouts/

2. Общий layout (не бизнес)

  • Используется несколькими страницами
  • Независим от бизнес-домена

📍 shared/components/layouts/

Примеры: EditorLayout, DashboardLayout, FullWidthLayout, CenteredLayout, ...

3. Под-layout (частичный layout)


a) Бизнес
  • Структурирует UI-секцию, связанную с доменом
  • Переиспользуется в нескольких экранах

📍 features/*/

b) Общий
  • Переиспользуемая структура UI
  • Без связи с бизнес-логикой

📍 shared/components/layouts/

Чего НЕ следует делать

  • ❌ Размещать layout в feature, если он определяется маршрутом
  • ❌ Размещать бизнес-layout в shared/

Быстрое правило

Маршрут выбирает layout

Feature предоставляет бизнес-UI Бизнес-под-layout’ы остаются внутри feature