253 lines
11 KiB
Markdown
253 lines
11 KiB
Markdown
|
|
---
|
|||
|
|
title: Слои
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Слои
|
|||
|
|
|
|||
|
|
Раздел описывает слои SLM: что такое слой, какие бывают, как между ними направлены зависимости и какие правила действуют на каждом.
|
|||
|
|
|
|||
|
|
## Определение
|
|||
|
|
|
|||
|
|
**Слой — уровень организации кода внутри `src/`. Каждый слой отвечает за свою область (каркас страницы, бизнес-логика, UI-кит) и задаёт правила для кода внутри: направление импортов, именование, допустимые связи между модулями.**
|
|||
|
|
|
|||
|
|
## Группы слоёв
|
|||
|
|
|
|||
|
|
Слои делятся на три группы:
|
|||
|
|
|
|||
|
|
| Группа | Слои | Описание |
|
|||
|
|
|--------|------|----------|
|
|||
|
|
| Композиция | `app`, `layouts`, `screens`, `widgets` | Собирают интерфейс из готовых блоков: маршруты, каркасы, страницы |
|
|||
|
|
| Ядро | `business`, `infrastructure`, `ui` | Реализация продукта: бизнес-домены, техсервисы, UI-кит |
|
|||
|
|
| Фундамент | `shared` | Общие ресурсы: утилиты, хелперы, стили, конфиги |
|
|||
|
|
|
|||
|
|
## Направление зависимостей
|
|||
|
|
|
|||
|
|
Любой импорт между модулями — только через публичный API.
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
app → [ layouts | screens ] → widgets → business → infrastructure → ui → shared
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- `layouts` и `screens` — параллельные слои, не импортируют друг друга
|
|||
|
|
- Модули одного слоя в группе «Композиция» изолированы друг от друга
|
|||
|
|
- Модули одного слоя `infrastructure` и `ui` могут импортировать друг друга через публичный API
|
|||
|
|
- Модули `business` — cross-domain зависимости по коду через фабрику, `import type` напрямую
|
|||
|
|
- Импорт типов (`import type`) в «Ядре» разрешён в обоих направлениях
|
|||
|
|
|
|||
|
|
|
|||
|
|
## Слой App
|
|||
|
|
|
|||
|
|
Точка входа приложения. Отвечает за запуск, роутинг и композицию маршрутов из layout и screen.
|
|||
|
|
|
|||
|
|
В отличие от остальных слоёв, `app/` не содержит модулей SLM. Здесь живут только инфраструктурные файлы, которые не могут быть никаким другим слоем: файлы фреймворка роутинга, точка запуска и код инициализации.
|
|||
|
|
|
|||
|
|
### Требования
|
|||
|
|
|
|||
|
|
- Не содержит модулей SLM — только файлы фреймворка, роутинг, инициализация
|
|||
|
|
- Содержит: файлы маршрутов, bootstrap, обработку ошибок верхнего уровня (404, error boundary), подключение глобальных стилей и ассетов
|
|||
|
|
- Провайдеры и гарды — только подключает готовые из нижних слоёв, не реализует
|
|||
|
|
- Не содержит бизнес-логику, UI-компоненты, хуки, сторы, сервисы
|
|||
|
|
- Никем не импортируется
|
|||
|
|
|
|||
|
|
## Слой Layouts
|
|||
|
|
|
|||
|
|
Каркас страницы: общие элементы, одинаковые для группы маршрутов (header, footer, sidebar).
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
src/layouts/
|
|||
|
|
├── main/
|
|||
|
|
├── dashboard/
|
|||
|
|
└── auth/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Требования
|
|||
|
|
|
|||
|
|
- Содержит только модули
|
|||
|
|
- Не содержит бизнес-логику
|
|||
|
|
- Контекстно-зависимые блоки принимает через пропсы от `app`, не импортирует напрямую
|
|||
|
|
|
|||
|
|
## Слой Screens
|
|||
|
|
|
|||
|
|
Контент конкретной страницы: собирает её из модулей нижних слоёв.
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
src/screens/
|
|||
|
|
├── home/
|
|||
|
|
├── products/
|
|||
|
|
├── product-detail/
|
|||
|
|
├── about/
|
|||
|
|
└── contacts/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Когда количество страниц затрудняет навигацию — вводится группировка по разделам. Группа — папка для организации, не модуль (без `index.ts`).
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
src/screens/
|
|||
|
|
├── shop/
|
|||
|
|
│ ├── home/
|
|||
|
|
│ ├── products/
|
|||
|
|
│ ├── product-detail/
|
|||
|
|
│ └── cart/
|
|||
|
|
├── account/
|
|||
|
|
│ ├── profile/
|
|||
|
|
│ ├── settings/
|
|||
|
|
│ └── order-history/
|
|||
|
|
└── info/
|
|||
|
|
├── about/
|
|||
|
|
├── contacts/
|
|||
|
|
└── faq/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Требования
|
|||
|
|
|
|||
|
|
- Содержит только модули
|
|||
|
|
- Не содержит бизнес-логику
|
|||
|
|
- Локальные одноразовые секции живут внутри screen-модуля, не выносятся в `widgets`/`business`
|
|||
|
|
|
|||
|
|
## Слой Widgets
|
|||
|
|
|
|||
|
|
Составной блок интерфейса, который компонует модули ядра, но не принадлежит конкретному бизнес-домену. Widget появляется когда блок используется в нескольких screens или layouts.
|
|||
|
|
|
|||
|
|
Если блок принадлежит домену — он живёт в `business/{area}/`, даже если переиспользуется. Если блок нужен только в одном месте — это `screens/{name}/parts/` или `layouts/{name}/parts/`, а не widget.
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
src/widgets/
|
|||
|
|
├── page-heading/
|
|||
|
|
├── hero-section/
|
|||
|
|
├── onboarding-checklist/
|
|||
|
|
├── promo-banner/
|
|||
|
|
└── error-boundary/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Требования
|
|||
|
|
|
|||
|
|
- Не принадлежит конкретному бизнес-домену. Если блок доменный — он живёт в `business/`
|
|||
|
|
- Используется в нескольких screens или layouts
|
|||
|
|
|
|||
|
|
## Слой Business
|
|||
|
|
|
|||
|
|
Бизнес-домены приложения: auth, catalog, orders, checkout, chat. Каждый домен — отдельный модуль со своими типами, логикой, UI и сервисами.
|
|||
|
|
|
|||
|
|
Слой входит в группу «Ядро». Импортирует `infrastructure/`, `ui/`, `shared/`. Cross-domain зависимости по коду реализуются через фабрику. `import type` между доменами разрешён напрямую.
|
|||
|
|
|
|||
|
|
Business объединяет то, что в FSD разделено на `features` и `entities`: пользовательские сценарии и бизнес-сущности живут вместе, внутри одного домена. Внутри домена сегменты разделяют ответственность: `types/` — доменная модель, `hooks/` и `services/` — сценарии и логика, `mappers/` — трансформация данных, `parts/` — составные блоки.
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
src/business/
|
|||
|
|
├── auth/
|
|||
|
|
├── catalog/
|
|||
|
|
├── orders/
|
|||
|
|
├── checkout/
|
|||
|
|
└── chat/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Когда количество доменов затрудняет навигацию — вводится группировка по субдоменам. Группа — папка для организации, не модуль (без `index.ts`).
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
src/business/
|
|||
|
|
├── commerce/
|
|||
|
|
│ ├── catalog/
|
|||
|
|
│ ├── cart/
|
|||
|
|
│ ├── orders/
|
|||
|
|
│ └── checkout/
|
|||
|
|
└── communication/
|
|||
|
|
├── chat/
|
|||
|
|
└── notifications/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Требования
|
|||
|
|
|
|||
|
|
- Один модуль = один бизнес-домен
|
|||
|
|
- Циклические зависимости между доменами запрещены
|
|||
|
|
- Импорт кода между доменами — через фабрику. `import type` — напрямую
|
|||
|
|
- Доменные типы (`User`, `Product`) живут здесь, не в `shared/`
|
|||
|
|
|
|||
|
|
## Слой Infrastructure
|
|||
|
|
|
|||
|
|
Техсервисы приложения: theme, i18n, API-адаптеры, logger, realtime. Каждый сервис — отдельный модуль.
|
|||
|
|
|
|||
|
|
Слой входит в группу «Ядро». Импортирует `infrastructure/`, `ui/`, `shared/`.
|
|||
|
|
|
|||
|
|
Отличие от `shared/`: infrastructure — инфраструктура приложения (сервисы, темы, адаптеры к API), `shared/` — общие ресурсы (утилиты, хелперы, стили, конфиги).
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
src/infrastructure/
|
|||
|
|
├── theme/
|
|||
|
|
├── i18n/
|
|||
|
|
├── backend-api/
|
|||
|
|
├── maps-api/
|
|||
|
|
├── logger/
|
|||
|
|
├── feature-flags/
|
|||
|
|
└── realtime/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Требования
|
|||
|
|
|
|||
|
|
- Один модуль = один техсервис
|
|||
|
|
- Импортирует `infrastructure/`, `ui/`, `shared/`
|
|||
|
|
|
|||
|
|
## Слой UI
|
|||
|
|
|
|||
|
|
UI-кит без бизнес-логики: button, carousel, toast, modal.
|
|||
|
|
|
|||
|
|
Слой входит в группу «Ядро». Импортирует `ui/` и `shared/`.
|
|||
|
|
|
|||
|
|
Компоненты строятся друг на друге: `button` использует `icon`, `carousel` использует `button`.
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
src/ui/
|
|||
|
|
├── button/
|
|||
|
|
├── input/
|
|||
|
|
├── icon/
|
|||
|
|
├── carousel/
|
|||
|
|
├── modal/
|
|||
|
|
├── toast/
|
|||
|
|
├── dropdown/
|
|||
|
|
├── tabs/
|
|||
|
|
└── tooltip/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Когда количество компонентов затрудняет навигацию — вводится группировка на примитивы и композиции. Примитивы (`button`, `icon`, `input`) не импортируют композиции. Композиции (`carousel`, `modal`, `dropdown`) строятся на примитивах.
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
src/ui/
|
|||
|
|
├── primitives/
|
|||
|
|
│ ├── button/
|
|||
|
|
│ ├── input/
|
|||
|
|
│ ├── icon/
|
|||
|
|
│ └── badge/
|
|||
|
|
└── composites/
|
|||
|
|
├── carousel/
|
|||
|
|
├── modal/
|
|||
|
|
├── dropdown/
|
|||
|
|
├── tabs/
|
|||
|
|
└── tooltip/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Требования
|
|||
|
|
|
|||
|
|
- Не содержит бизнес-логику
|
|||
|
|
- Импортирует только `ui/` и `shared/`
|
|||
|
|
|
|||
|
|
## Слой Shared
|
|||
|
|
|
|||
|
|
Общие ресурсы: утилиты, хелперы, стили, конфиги. Не знает о бизнес-домене.
|
|||
|
|
|
|||
|
|
Слой входит в группу «Фундамент» — ни о ком не знает, никого не импортирует.
|
|||
|
|
|
|||
|
|
Отличие от `infrastructure/`: infrastructure — инфраструктура приложения (сервисы, темы, адаптеры к API), `shared/` — общие ресурсы (утилиты, хелперы, стили, конфиги).
|
|||
|
|
|
|||
|
|
Отличие от `ui/`: UI-компоненты (button, carousel, modal) живут в слое `ui/`, а не здесь.
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
src/shared/
|
|||
|
|
├── lib/
|
|||
|
|
├── types/
|
|||
|
|
├── styles/
|
|||
|
|
└── sprites/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Требования
|
|||
|
|
|
|||
|
|
- Не имеет runtime-состояния
|