docs: обновить архитектуру SLM compositions
- обновлена модель слоёв на app → compositions → business → infra → ui → shared - добавлены правила composition modules и providers-сегмента - обновлены правила монорепозитория для слоя compositions - переписаны React-примеры под page-level композицию - добавлен пример вариантов структуры compositions
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Модули
|
||||
description: Структура модуля, типы (UI, бизнес, инфра), публичный API, отличие модуля от компонента
|
||||
description: Структура модуля, типы (композиционный, UI, бизнес, инфра), публичный API, отличие модуля от компонента
|
||||
---
|
||||
|
||||
# Модули
|
||||
@@ -13,7 +13,7 @@ description: Структура модуля, типы (UI, бизнес, инф
|
||||
|
||||
Модуль может содержать всё, что нужно этой области: компоненты, вложенные модули, хуки, сторы, сервисы, типы, стили, конфиги и утилиты. Набор сегментов не фиксирован — модуль включает только то, что реально нужно.
|
||||
|
||||
Модуль не обязан быть UI-блоком. Это может быть страница, виджет, бизнес-домен, инфраструктурный сервис или UI-kit сущность.
|
||||
Модуль не обязан быть UI-блоком. Это может быть page composition, layout composition, screen composition, widget composition, бизнес-домен, инфраструктурный сервис или UI-kit сущность.
|
||||
|
||||
Главная граница модуля — не папка, а ответственность.
|
||||
|
||||
@@ -63,30 +63,62 @@ auth/
|
||||
|
||||
Примеры модулей:
|
||||
|
||||
- `screens/home/` — модуль страницы.
|
||||
- `widgets/page-heading/` — модуль виджета.
|
||||
- `compositions/pages/home/` — модуль page composition.
|
||||
- `compositions/layouts/main/` — модуль layout composition.
|
||||
- `compositions/screens/profile/` — модуль screen composition.
|
||||
- `compositions/widgets/page-heading/` — модуль widget composition.
|
||||
- `business/auth/` — модуль бизнес-домена.
|
||||
- `infra/theme/` — модуль инфраструктурного сервиса.
|
||||
- `ui/button/` — модуль UI-kit сущности.
|
||||
- `screens/home/parts/hero-section/` — вложенный модуль страницы.
|
||||
- `compositions/pages/home/parts/hero-section/` — вложенный модуль page composition.
|
||||
|
||||
Не считаются модулями:
|
||||
|
||||
- `ui/`, `parts/`, `hooks/`, `types/`, `styles/`, `config/` — это сегменты.
|
||||
- `screens/shop/`, `business/commerce/` — это группы, если в них нет `index.ts`.
|
||||
- `screens/home/ui/user-card/` — это компонент, если он находится в `ui/` и соблюдает ограничения компонента.
|
||||
- `ui/`, `parts/`, `hooks/`, `types/`, `styles/`, `config/`, `providers/` — это сегменты.
|
||||
- `compositions/pages/`, `business/commerce/` — это группы, если в них нет `index.ts`.
|
||||
- `compositions/pages/home/ui/user-card/` — это компонент, если он находится в `ui/` и соблюдает ограничения компонента.
|
||||
|
||||
## Типы модулей
|
||||
|
||||
Тип модуля определяет обязательный корневой файл и стартовую структуру.
|
||||
|
||||
### Композиционный модуль
|
||||
|
||||
Композиционный модуль — модуль внутри `compositions`, который участвует в сборке страниц, маршрутов и крупных продуктовых частей интерфейса.
|
||||
|
||||
Он может быть page, layout, screen, widget, block, entry-point, CMS-entry, route segment или другим типом композиции, выбранным командой.
|
||||
|
||||
```text
|
||||
compositions/pages/profile/
|
||||
├── profile.page.tsx
|
||||
├── profile-business-composition.ts
|
||||
├── providers/
|
||||
├── hooks/
|
||||
├── stores/
|
||||
├── parts/
|
||||
├── types/
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
Композиционный модуль может импортировать другие composition modules через public API. Это отличие слоя `compositions`: внутри него допускается графовая композиция.
|
||||
|
||||
При этом deep imports запрещены.
|
||||
|
||||
```ts
|
||||
// Хорошо
|
||||
import { useProfilePageStore } from '@/compositions/pages/profile'
|
||||
|
||||
// Плохо
|
||||
import { useProfilePageStore } from '@/compositions/pages/profile/hooks/use-profile-page-store.hook'
|
||||
```
|
||||
|
||||
### UI-модуль
|
||||
|
||||
Модуль строится вокруг основного UI-компонента и обязан иметь основной `.tsx` файл в корне:
|
||||
|
||||
```text
|
||||
header/
|
||||
├── header.tsx
|
||||
button/
|
||||
├── button.tsx
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
@@ -94,7 +126,7 @@ header/
|
||||
|
||||
### Бизнес-модуль
|
||||
|
||||
Бизнес-модуль — модуль, который строится вокруг публичного runtime API.
|
||||
Бизнес-модуль — модуль, который строится вокруг публичного API фабрики.
|
||||
|
||||
Бизнес-модуль обязан иметь фабрику в корне:
|
||||
|
||||
@@ -105,7 +137,7 @@ auth/
|
||||
└── types/
|
||||
```
|
||||
|
||||
Фабрика возвращает публичный runtime API модуля.
|
||||
Фабрика возвращает публичный API модуля для использования в runtime.
|
||||
|
||||
### Инфраструктурный модуль
|
||||
|
||||
@@ -140,6 +172,7 @@ backend-api/
|
||||
├── {module-name}.tsx # корневой файл модуля (опционален)
|
||||
├── ui/ # компоненты модуля
|
||||
├── parts/ # вложенные модули
|
||||
├── providers/ # провайдеры модуля
|
||||
├── hooks/ # хуки
|
||||
├── stores/ # сторы состояния
|
||||
├── services/ # внешние источники данных
|
||||
@@ -184,32 +217,49 @@ export type { CustomerDeps } from './types/customer-deps.type'
|
||||
export type { CustomerFactory } from './types/customer-factory.type'
|
||||
```
|
||||
|
||||
Composition module экспортирует через `index.ts` только безопасный контракт, который нужен другим composition modules или `app`: page/layout/screen/widget, provider, hooks доступа, типы. Внутренние stores, context objects и функции создания состояния не экспортируются без необходимости.
|
||||
|
||||
Если layout, screen или widget импортируют hooks из page composition, не смешивайте в одном public API готовую page composition и hooks для дочерних модулей: это может создать runtime-цикл.
|
||||
|
||||
```ts
|
||||
// compositions/pages/profile/index.ts
|
||||
export { ProfilePageProvider } from './providers/profile-page.provider'
|
||||
export { useProfilePageStore } from './hooks/use-profile-page-store.hook'
|
||||
export { useProfileBusinessComposition } from './hooks/use-profile-business-composition.hook'
|
||||
|
||||
export type { ProfilePageState } from './types/profile-page-state.type'
|
||||
```
|
||||
|
||||
## Фабрика
|
||||
|
||||
Business-модуль всегда экспортирует фабрику. Фабрика лежит в корне модуля (`{name}.factory.ts`), типизируется через `{Name}Factory` и возвращает публичный runtime API модуля.
|
||||
Business-модуль всегда экспортирует фабрику. Фабрика лежит в корне модуля (`{name}.factory.ts`), типизируется через `{Name}Factory` и возвращает публичный API фабрики.
|
||||
|
||||
Всё, что нужно внешнему коду в runtime, должно быть частью API, который возвращает фабрика.
|
||||
|
||||
Модуль без cross-domain зависимостей экспортирует фабрику без аргументов. Модуль с зависимостями — фабрику, принимающую зависимости доменными именами. Типы всегда экспортируются напрямую через `export type` — `import type` не является runtime-зависимостью.
|
||||
|
||||
Компоновка фабрик происходит на уровне модуля-потребителя: screen, layout, widget или любой другой модуль группы «Композиция».
|
||||
Компоновка фабрик происходит в модуле-потребителе на слое `compositions`.
|
||||
|
||||
### Примеры
|
||||
|
||||
Пример реализации фабрики в React см. в [Создание фабрики](/examples/react/factory).
|
||||
|
||||
Пример композиции фабрик в React screen-модуле см. в [Композиция фабрик](/examples/react/factory-composition).
|
||||
Пример композиции фабрик в React composition module см. в [Композиция фабрик](/examples/react/factory-composition).
|
||||
|
||||
Пример композиции фабрик через React Provider см. в [Композиция через Provider](/examples/react/composition-provider).
|
||||
Пример page-level Provider в React см. в [Композиция через Provider](/examples/react/composition-provider).
|
||||
|
||||
Примеры разных структур слоя `compositions` см. в [Структуры compositions](/examples/react/composition-structures).
|
||||
|
||||
## Жизненный цикл
|
||||
|
||||
Модуль рождается на самом низком уровне использования и поднимается выше только при реальной потребности.
|
||||
|
||||
- Нужен на одной странице → `screens/{name}/parts/`
|
||||
- Появился в 2+ местах → поднимается по природе:
|
||||
- абстрактный UI → `ui/`
|
||||
- блок с данными/логикой → `widgets/`
|
||||
- представление бизнес-домена → `business/{area}/parts/`
|
||||
- Нужен одной странице, route branch или крупной продуктовой части интерфейса → внутри соответствующего composition module.
|
||||
- Нужен нескольким частям одной страницы → внутри page composition или другого общего composition scope.
|
||||
- Нужен нескольким страницам или маршрутам → отдельный composition module внутри `compositions`.
|
||||
- Абстрактный UI без бизнес-логики → `ui/`.
|
||||
- Представление или сценарий бизнес-домена → `business/{domain}/`.
|
||||
- Технический сервис → `infra/`.
|
||||
- Общая чистая утилита → `shared/`.
|
||||
|
||||
Подъём — обычный рефакторинг в рамках задачи, а не отдельная активность.
|
||||
|
||||
Reference in New Issue
Block a user