forked from templates/nextjs-template
style: Обновлены правила код стайла
This commit is contained in:
@@ -1,162 +1,156 @@
|
||||
---
|
||||
title: Модуль
|
||||
description: Как создавать и организовывать SLM-модули в проекте.
|
||||
description: Как должен выглядеть сгенерированный SLM-модуль в проекте.
|
||||
---
|
||||
|
||||
# Модуль
|
||||
|
||||
Как создавать и организовывать SLM-модули в проекте.
|
||||
Как должен выглядеть сгенерированный SLM-модуль в проекте.
|
||||
|
||||
## Назначение
|
||||
|
||||
Модуль — основной строительный блок SLM-архитектуры. Это папка с публичным API (`index.ts`) и опциональными сегментами: компонентами, стилями, типами, хуками, сторами, сервисами и вложенными модулями.
|
||||
Архитектурное определение модуля описано в разделе [Архитектура → Модули](../basics/architecture/modules.md). Список сегментов описан в разделе [Архитектура → Сегменты](../basics/architecture/segments.md).
|
||||
|
||||
Если UI-сущность остаётся одним `.tsx` файлом и использует ресурсы родительского модуля — это [компонент](./component.md), а не модуль. Связанные файлы в `styles/` и `types/` родителя не создают новую модульную границу.
|
||||
Эта страница показывает прикладное оформление трёх типов модулей: UI, бизнес и инфраструктурный.
|
||||
|
||||
Архитектурное определение: [Модули SLM](../basics/architecture/reference/modules.md). Список сегментов: [Сегменты SLM](../basics/architecture/reference/segments.md).
|
||||
## Создание
|
||||
|
||||
## Когда нужен модуль
|
||||
1. Проверьте, что в проекте есть нужный шаблон в `.templates/`.
|
||||
2. Если шаблона нет — создайте его по разделу [Создание шаблонов](./templates/templates-create.md).
|
||||
3. Сгенерируйте модуль через [VS Code или CLI](./templates/templates-usage.md).
|
||||
|
||||
Создавайте модуль, если сущности нужны:
|
||||
## Типы модулей
|
||||
|
||||
- публичный API;
|
||||
- хуки, сторы, сервисы, мапперы или утилиты;
|
||||
- вложенные части;
|
||||
- переиспользование вне родительского модуля;
|
||||
- самостоятельная ответственность на слое.
|
||||
Архитектура определяет три типа модулей ([Типы модулей](../basics/architecture/modules.md#типы-модулей)):
|
||||
|
||||
Если понадобилась папка вокруг компонента — это сигнал, что нужен модуль.
|
||||
| Тип | Обязательный файл | Описание |
|
||||
|---|---|---|
|
||||
| UI-модуль | `{name}.tsx` | Модуль, выросший из компонента |
|
||||
| Бизнес-модуль | `{name}.factory.ts` | Модуль вокруг публичного runtime API |
|
||||
| Инфраструктурный модуль | нет | Модуль вокруг технического сервиса |
|
||||
|
||||
## Где размещать
|
||||
## UI-модуль
|
||||
|
||||
Модуль размещается на самом низком уровне использования.
|
||||
UI-модуль — это компонент, который перерос ограничения компонента: получил собственные хуки, вложенные модули в `parts/`, сценарную логику или публичный API. Внутренняя структура та же, что у компонента: корневой `.tsx`, типы, стили, `ui/`. Но без ограничений компонента.
|
||||
|
||||
- Нужен только одному модулю — размещается в `parts/` родителя.
|
||||
- Нужен одной странице — размещается в `screens/{name}/parts/`.
|
||||
- Нужен одному layout — размещается в `layouts/{name}/parts/`.
|
||||
- Переиспользуется между страницами или layout — поднимается в `widgets/`.
|
||||
- Представляет бизнес-домен — размещается в `business/`.
|
||||
- Является UI-китом — размещается в `ui/`.
|
||||
Подробное оформление компонентов внутри `ui/` описано в разделе [Компонент](./component.md).
|
||||
|
||||
`app/` не содержит модулей. Это слой файлового роутинга и инициализации.
|
||||
## Бизнес-модуль
|
||||
|
||||
## Структура
|
||||
Бизнес-модуль строится вокруг публичного runtime API. Ключевой файл — фабрика (`{name}.factory.ts`), которая возвращает всё, что нужно внешнему коду в runtime.
|
||||
|
||||
Минимальный UI-модуль:
|
||||
Архитектурное описание фабрики: [Архитектура → Фабрика](../basics/architecture/modules.md#фабрика).
|
||||
|
||||
### Структура
|
||||
|
||||
```text
|
||||
user/
|
||||
├── user.tsx
|
||||
└── index.ts
|
||||
business/customer/
|
||||
├── customer.factory.ts
|
||||
├── index.ts
|
||||
└── types/
|
||||
├── customer.type.ts
|
||||
├── customer-api.type.ts
|
||||
├── customer-deps.type.ts
|
||||
└── customer-factory.type.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` — единственная точка входа в модуль. Внешние импорты внутренних файлов запрещены.
|
||||
`business/customer/types/customer-api.type.ts`
|
||||
|
||||
```ts
|
||||
// user/index.ts
|
||||
export { User } from './user'
|
||||
export type { UserProps } from './types/user.type'
|
||||
export type CustomerApi = {
|
||||
useCustomer: () => Customer
|
||||
CustomerCard: (props: CustomerCardProps) => ReactNode
|
||||
}
|
||||
```
|
||||
|
||||
`business/order/types/order-deps.type.ts`
|
||||
|
||||
```ts
|
||||
// Плохо: импорт в обход публичного API.
|
||||
import { UserPosts } from 'screens/user/parts/user-posts/user-posts'
|
||||
|
||||
// Хорошо: импорт через публичный API родительского модуля.
|
||||
import { User } from 'screens/user'
|
||||
export type OrderDeps = {
|
||||
customer: Pick<CustomerApi, 'useCustomer'>
|
||||
}
|
||||
```
|
||||
|
||||
Вложенный модуль имеет свой `index.ts`, но наружу родителя экспортируется только при необходимости.
|
||||
`business/order/types/order-factory.type.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
|
||||
```ts
|
||||
export type OrderFactory = (deps: OrderDeps) => OrderApi
|
||||
```
|
||||
|
||||
### Business-модуль без корневого компонента
|
||||
### Фабрика без зависимостей
|
||||
|
||||
`business/customer/customer.factory.ts`
|
||||
|
||||
```ts
|
||||
import type { CustomerFactory } from './types/customer-factory.type'
|
||||
|
||||
export const customerFactory: CustomerFactory = () => {
|
||||
return {
|
||||
useCustomer,
|
||||
CustomerCard,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Фабрика с зависимостями
|
||||
|
||||
`business/order/order.factory.ts`
|
||||
|
||||
```ts
|
||||
import type { OrderFactory } from './types/order-factory.type'
|
||||
|
||||
export const orderFactory: OrderFactory = (deps) => {
|
||||
return {
|
||||
useOrder,
|
||||
OrderCard,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Композиция на уровне screen
|
||||
|
||||
```tsx
|
||||
// screens/home/home.screen.tsx
|
||||
import { customerFactory } from '@/business/customer'
|
||||
import { orderFactory } from '@/business/order'
|
||||
|
||||
const customer = customerFactory()
|
||||
const order = orderFactory({ customer })
|
||||
|
||||
const { useOrder, OrderCard } = order
|
||||
|
||||
export const HomeScreen = () => {
|
||||
const currentOrder = useOrder()
|
||||
|
||||
return <OrderCard order={currentOrder} />
|
||||
}
|
||||
```
|
||||
|
||||
## Инфраструктурный модуль
|
||||
|
||||
Инфраструктурный модуль строится вокруг технического сервиса или интеграции. Его структура определяется природой сервиса — фиксированного корневого файла нет.
|
||||
|
||||
Архитектурное описание: [Архитектура → Типы модулей → Инфраструктурный модуль](../basics/architecture/modules.md#инфраструктурный-модуль).
|
||||
|
||||
Пример модуля темы:
|
||||
|
||||
```text
|
||||
business/auth/
|
||||
theme/
|
||||
├── index.ts
|
||||
├── config/
|
||||
├── hooks/
|
||||
│ └── use-auth.hook.ts
|
||||
├── services/
|
||||
│ └── auth.service.ts
|
||||
├── stores/
|
||||
│ └── auth.store.ts
|
||||
├── styles/
|
||||
└── ui/
|
||||
```
|
||||
|
||||
Пример модуля API-клиента:
|
||||
|
||||
```text
|
||||
backend-api/
|
||||
├── backend-api.client.ts
|
||||
├── config/
|
||||
├── types/
|
||||
│ └── auth.type.ts
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user