163 lines
6.8 KiB
Markdown
163 lines
6.8 KiB
Markdown
|
|
---
|
|||
|
|
title: Модуль
|
|||
|
|
description: Как создавать и организовывать SLM-модули в проекте.
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Модуль
|
|||
|
|
|
|||
|
|
Как создавать и организовывать SLM-модули в проекте.
|
|||
|
|
|
|||
|
|
## Назначение
|
|||
|
|
|
|||
|
|
Модуль — основной строительный блок SLM-архитектуры. Это папка с публичным API (`index.ts`) и опциональными сегментами: компонентами, стилями, типами, хуками, сторами, сервисами и вложенными модулями.
|
|||
|
|
|
|||
|
|
Если UI-сущность остаётся одним `.tsx` файлом и использует ресурсы родительского модуля — это [компонент](./component.md), а не модуль. Связанные файлы в `styles/` и `types/` родителя не создают новую модульную границу.
|
|||
|
|
|
|||
|
|
Архитектурное определение: [Модули SLM](../basics/architecture/reference/modules.md). Список сегментов: [Сегменты SLM](../basics/architecture/reference/segments.md).
|
|||
|
|
|
|||
|
|
## Когда нужен модуль
|
|||
|
|
|
|||
|
|
Создавайте модуль, если сущности нужны:
|
|||
|
|
|
|||
|
|
- публичный API;
|
|||
|
|
- хуки, сторы, сервисы, мапперы или утилиты;
|
|||
|
|
- вложенные части;
|
|||
|
|
- переиспользование вне родительского модуля;
|
|||
|
|
- самостоятельная ответственность на слое.
|
|||
|
|
|
|||
|
|
Если понадобилась папка вокруг компонента — это сигнал, что нужен модуль.
|
|||
|
|
|
|||
|
|
## Где размещать
|
|||
|
|
|
|||
|
|
Модуль размещается на самом низком уровне использования.
|
|||
|
|
|
|||
|
|
- Нужен только одному модулю — размещается в `parts/` родителя.
|
|||
|
|
- Нужен одной странице — размещается в `screens/{name}/parts/`.
|
|||
|
|
- Нужен одному layout — размещается в `layouts/{name}/parts/`.
|
|||
|
|
- Переиспользуется между страницами или layout — поднимается в `widgets/`.
|
|||
|
|
- Представляет бизнес-домен — размещается в `business/`.
|
|||
|
|
- Является UI-китом — размещается в `ui/`.
|
|||
|
|
|
|||
|
|
`app/` не содержит модулей. Это слой файлового роутинга и инициализации.
|
|||
|
|
|
|||
|
|
## Структура
|
|||
|
|
|
|||
|
|
Минимальный UI-модуль:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
user/
|
|||
|
|
├── user.tsx
|
|||
|
|
└── index.ts
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Модуль расширяется сегментами только при реальной потребности:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
user/
|
|||
|
|
├── ui/
|
|||
|
|
│ └── user-avatar.tsx
|
|||
|
|
├── parts/
|
|||
|
|
│ └── user-posts/
|
|||
|
|
│ ├── user-posts.tsx
|
|||
|
|
│ └── index.ts
|
|||
|
|
├── styles/
|
|||
|
|
│ ├── user.module.css
|
|||
|
|
│ └── user-avatar.module.css
|
|||
|
|
├── types/
|
|||
|
|
│ ├── user.type.ts
|
|||
|
|
│ └── user-avatar.type.ts
|
|||
|
|
├── user.tsx
|
|||
|
|
└── index.ts
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Корневой компонент опционален. Business- и infrastructure-модули могут состоять только из хуков, сервисов, типов и публичного API.
|
|||
|
|
|
|||
|
|
## `ui/` и `parts/`
|
|||
|
|
|
|||
|
|
`ui/` содержит только компоненты: отдельные `.tsx` файлы без собственных сегментов.
|
|||
|
|
|
|||
|
|
`parts/` содержит только модули: каждая запись внутри `parts/` — папка с собственным `index.ts`. Отдельные `.tsx`, стили, хуки или произвольные файлы в `parts/` не кладутся.
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
user/
|
|||
|
|
├── ui/
|
|||
|
|
│ └── user-avatar.tsx # компонент
|
|||
|
|
└── parts/
|
|||
|
|
└── user-posts/ # модуль
|
|||
|
|
├── styles/
|
|||
|
|
│ └── user-posts.module.css
|
|||
|
|
├── user-posts.tsx
|
|||
|
|
└── index.ts
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Если компоненту в `ui/` понадобились стили или типы, они добавляются в `styles/` и `types/` родительского модуля. Если компоненту нужны собственные хуки, вложенные части или публичная граница — он переносится в `parts/` как модуль.
|
|||
|
|
|
|||
|
|
## Публичный API
|
|||
|
|
|
|||
|
|
`index.ts` — единственная точка входа в модуль. Внешние импорты внутренних файлов запрещены.
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
// user/index.ts
|
|||
|
|
export { User } from './user'
|
|||
|
|
export type { UserProps } from './types/user.type'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
// Плохо: импорт в обход публичного API.
|
|||
|
|
import { UserPosts } from 'screens/user/parts/user-posts/user-posts'
|
|||
|
|
|
|||
|
|
// Хорошо: импорт через публичный API родительского модуля.
|
|||
|
|
import { User } from 'screens/user'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Вложенный модуль имеет свой `index.ts`, но наружу родителя экспортируется только при необходимости.
|
|||
|
|
|
|||
|
|
## Именование
|
|||
|
|
|
|||
|
|
Базовые правила описаны в разделе [Именование](../basics/naming.md).
|
|||
|
|
|
|||
|
|
- Папка модуля — `kebab-case`: `user-posts/`.
|
|||
|
|
- Файл корневого компонента повторяет имя папки: `user-posts/user-posts.tsx`.
|
|||
|
|
- Корневые модули слоёв наследуют роль слоя в имени файла: `screens/profile/profile.screen.tsx`, `layouts/main/main.layout.tsx`.
|
|||
|
|
- Корневой компонент именуется в `PascalCase`: `UserPosts`.
|
|||
|
|
- Если имя без контекста слишком общее, добавляется префикс родителя или роль слоя: `ProfileUserPosts`, `ProfileScreen`, `MainLayout`.
|
|||
|
|
|
|||
|
|
## Примеры
|
|||
|
|
|
|||
|
|
### Screen-модуль
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
screens/profile/
|
|||
|
|
├── ui/
|
|||
|
|
│ └── profile-heading.tsx
|
|||
|
|
├── parts/
|
|||
|
|
│ └── activity-feed/
|
|||
|
|
│ ├── styles/
|
|||
|
|
│ │ └── activity-feed.module.css
|
|||
|
|
│ ├── activity-feed.tsx
|
|||
|
|
│ └── index.ts
|
|||
|
|
├── styles/
|
|||
|
|
│ ├── profile.module.css
|
|||
|
|
│ └── profile-heading.module.css
|
|||
|
|
├── types/
|
|||
|
|
│ ├── profile.type.ts
|
|||
|
|
│ └── profile-heading.type.ts
|
|||
|
|
├── profile.screen.tsx
|
|||
|
|
└── index.ts
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Business-модуль без корневого компонента
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
business/auth/
|
|||
|
|
├── hooks/
|
|||
|
|
│ └── use-auth.hook.ts
|
|||
|
|
├── services/
|
|||
|
|
│ └── auth.service.ts
|
|||
|
|
├── stores/
|
|||
|
|
│ └── auth.store.ts
|
|||
|
|
├── types/
|
|||
|
|
│ └── auth.type.ts
|
|||
|
|
└── index.ts
|
|||
|
|
```
|