- Добавлена документация SLM-архитектуры, базовых правил и прикладных разделов - Добавлены разделы: стили, SVG-спрайты, шаблоны генерации, PostCSS, REST, Realtime - Удалены устаревшие файлы (спрайты, скрипты, стили из app/)
166 lines
6.5 KiB
Markdown
166 lines
6.5 KiB
Markdown
---
|
||
title: Модули SLM
|
||
description: Что такое модуль в SLM-архитектуре и как он устроен.
|
||
---
|
||
|
||
# Модули SLM
|
||
|
||
Что такое модуль в SLM-архитектуре и как он устроен.
|
||
|
||
## Определение
|
||
|
||
**Модуль — универсальный строительный блок архитектуры. Живёт на слое и содержит всё необходимое для своей работы: компоненты, хуки, сторы, сервисы, типы, стили. Набор содержимого не фиксирован — включаются только нужные части.**
|
||
|
||
## Модуль vs компонент
|
||
|
||
**Компонент** — один `.tsx` файл. Не имеет своих сегментов, использует сегменты родительского модуля. Живёт в корне или `ui/` сегменте модуля.
|
||
|
||
**Модуль** — папка, которая может содержать корневой компонент, сегменты (`hooks/`, `types/`, `styles/`, `ui/`, `parts/` и т.д.) и публичный API (`index.ts`).
|
||
|
||
```text
|
||
auth/
|
||
├── ui/
|
||
│ ├── auth-guard.tsx
|
||
│ └── logout-button.tsx
|
||
├── parts/
|
||
│ ├── login-form/
|
||
│ ├── registration-form/
|
||
│ └── restore-form/
|
||
├── hooks/
|
||
├── stores/
|
||
├── types/
|
||
├── auth.tsx # корневой компонент (опционален)
|
||
└── index.ts
|
||
```
|
||
|
||
## Структура
|
||
|
||
Модуль состоит из сегментов. Ни один сегмент не обязателен — модуль может состоять даже из одного `index.ts` с реэкспортом типов.
|
||
|
||
```text
|
||
{module-name}/
|
||
├── {module-name}.tsx # корневой компонент (опционален)
|
||
├── ui/ # компоненты модуля (только .tsx)
|
||
├── parts/ # вложенные модули (со своими сегментами)
|
||
├── hooks/ # хуки
|
||
├── stores/ # сторы состояния
|
||
├── services/ # внешние источники данных
|
||
├── mappers/ # трансформация данных между форматами
|
||
├── types/ # типы
|
||
├── styles/ # стили
|
||
├── lib/ # утилиты модуля
|
||
├── config/ # константы
|
||
└── index.ts # публичный API
|
||
```
|
||
|
||
Подробное описание каждого сегмента — в разделе [Сегменты](./segments.md).
|
||
|
||
## Публичный API
|
||
|
||
Модуль экспортирует наружу только то, что нужно другим. Всё остальное — внутреннее.
|
||
|
||
```ts
|
||
// business/auth/index.ts
|
||
export type { User, Session } from './types/user.types'
|
||
export { useAuth } from './hooks/use-auth.hook'
|
||
export { AuthGuard } from './ui/auth-guard'
|
||
```
|
||
|
||
Импорт в обход `index.ts` запрещён:
|
||
|
||
```ts
|
||
// Плохо
|
||
import { validateToken } from '@/business/auth/lib/tokens'
|
||
|
||
// Хорошо
|
||
import { useAuth } from '@/business/auth'
|
||
```
|
||
|
||
## Фабрика
|
||
|
||
Если модуль зависит от кода другого бизнес-домена — он экспортирует фабрику. Фабрика декларирует необходимые зависимости и возвращает API модуля. Точка использования (screen, widget, layout) предоставляет зависимости при вызове.
|
||
|
||
Модуль без cross-domain зависимостей экспортирует API напрямую. Типы всегда экспортируются напрямую — `import type` не является runtime-зависимостью.
|
||
|
||
### Модуль без зависимостей — прямой экспорт:
|
||
|
||
```ts
|
||
// business/auth/index.ts
|
||
export { useAuth } from './hooks/use-auth'
|
||
export { useCurrentUser } from './hooks/use-current-user'
|
||
export type { User, Session } from './types'
|
||
```
|
||
|
||
### Модуль с зависимостями — фабрика:
|
||
|
||
```ts
|
||
// business/chat/types/deps.ts
|
||
import type { User } from '@/business/auth'
|
||
|
||
export interface ChatDeps {
|
||
useCurrentUser: () => User | null
|
||
}
|
||
```
|
||
|
||
```ts
|
||
// business/chat/index.ts
|
||
import type { ChatDeps } from './types/deps'
|
||
|
||
export function chatFactory(deps: ChatDeps) {
|
||
return {
|
||
useMessages: (roomId: string) => {
|
||
const user = deps.useCurrentUser()
|
||
// ...
|
||
},
|
||
useSendMessage: (roomId: string) => {
|
||
const user = deps.useCurrentUser()
|
||
return (text: string) => { /* ... */ }
|
||
},
|
||
useChatRooms: () => {
|
||
const user = deps.useCurrentUser()
|
||
// ...
|
||
},
|
||
ChatBadge: ({ count }: { count: number }) => { /* ... */ },
|
||
}
|
||
}
|
||
|
||
export type { Message, ChatRoom } from './types'
|
||
export type { ChatDeps } from './types/deps'
|
||
```
|
||
|
||
### Использование на странице:
|
||
|
||
```tsx
|
||
// screens/support/support.tsx
|
||
import { useCurrentUser } from '@/business/auth'
|
||
import { chatFactory } from '@/business/chat'
|
||
|
||
const chat = chatFactory({ useCurrentUser })
|
||
|
||
export function SupportScreen() {
|
||
const { useMessages, useSendMessage, ChatBadge } = chat
|
||
const messages = useMessages('support')
|
||
const sendMessage = useSendMessage('support')
|
||
|
||
return (
|
||
<div>
|
||
<ChatBadge count={messages.length} />
|
||
{messages.map(m => <MessageBubble key={m.id} {...m} />)}
|
||
<MessageInput onSend={sendMessage} />
|
||
</div>
|
||
)
|
||
}
|
||
```
|
||
|
||
## Жизненный цикл
|
||
|
||
Модуль рождается на самом низком уровне использования и поднимается выше только при реальной потребности.
|
||
|
||
- Нужен на одной странице → `screens/{name}/parts/`
|
||
- Появился в 2+ местах → поднимается по природе:
|
||
- абстрактный UI → `ui/`
|
||
- блок с данными/логикой → `widgets/`
|
||
- представление бизнес-домена → `business/{area}/parts/`
|
||
|
||
Подъём — обычный рефакторинг в рамках задачи, а не отдельная активность.
|