Обновить notes
This commit is contained in:
133
notes
133
notes
@@ -4,16 +4,125 @@
|
|||||||
|
|
||||||
Проблема, неочевидность слоев (наследие FSD)
|
Проблема, неочевидность слоев (наследие FSD)
|
||||||
|
|
||||||
Нет четкого понимания что виджет - это собраные переиспользуемые блоки на всех раздела сайта (пример: слайдеры, итд..)
|
|
||||||
|
|
||||||
Честный ответ — из style guide это неочевидно. Вот что там написано про слои:
|
Архитектурные слои проекта
|
||||||
- shared/ui — переиспользуемые UI-компоненты без бизнес-логики
|
Каждый нижний слой не знает о существовании верхних. Импорты идут только сверху вниз.
|
||||||
- widgets — самодостаточные блоки интерфейса
|
pages → layouts → screens → widgets → features → entities → shared
|
||||||
- screens — экраны, собирают виджеты
|
---
|
||||||
Но нет чёткого правила: "если компонент используется только на одной странице — он дочерний компонент screen, а не widget". Style guide описывает что такое каждый слой, но не описывает критерий выбора между ними.
|
1. Pages (pages/)
|
||||||
Я по умолчанию положил всё в widgets/ потому что style guide говорит "screen собирается из виджетов" — и я буквально так и сделал. Это ошибка интерпретации.
|
Точка входа маршрута. Только связывает layout и screen.
|
||||||
Что стоит дополнить в style guide
|
Правила:
|
||||||
Критерий размещения:
|
- Никакой логики, стилей, разметки кроме композиции
|
||||||
Переиспользуется на 2+ страницах?
|
- Один page = один layout + один screen
|
||||||
├── Да → shared/ui (компонент) или widgets/ (составной блок)
|
Пример:
|
||||||
└── Нет → screens/{name}/ui/ (дочерний компонент экрана)
|
// pages/knv-new.js
|
||||||
|
import { KnvScreen } from 'src/screens/knv'
|
||||||
|
import { MainLayout } from 'src/layouts/main'
|
||||||
|
const KnvNewPage = () => (
|
||||||
|
<MainLayout>
|
||||||
|
<KnvScreen />
|
||||||
|
</MainLayout>
|
||||||
|
)
|
||||||
|
---
|
||||||
|
2. Layouts (src/layouts/)
|
||||||
|
Каркас страницы — общие элементы, которые одинаковы на всех страницах в рамках этого layout.
|
||||||
|
Содержит в ui/: header, footer, sidebar — дочерние компоненты, которые привязаны к layout и не переиспользуются отдельно.
|
||||||
|
Критерий: компонент одинаков на всех страницах, использующих этот layout? → layouts/{name}/ui/
|
||||||
|
Пример:
|
||||||
|
src/layouts/main/
|
||||||
|
├── main.layout.tsx # <Header /> + children + <Footer />
|
||||||
|
├── ui/
|
||||||
|
│ ├── header/ # всегда одинаковый на всех страницах
|
||||||
|
│ └── footer/ # всегда одинаковый на всех страницах
|
||||||
|
---
|
||||||
|
3. Screens (src/screens/)
|
||||||
|
Контент конкретной страницы. Собирает свои секции и переиспользуемые widgets/features/entities.
|
||||||
|
Содержит в ui/: блоки, которые существуют только на этой странице и не переиспользуются.
|
||||||
|
Критерий: компонент используется только на одной странице? → screens/{name}/ui/
|
||||||
|
Пример:
|
||||||
|
src/screens/knv/
|
||||||
|
├── knv.screen.tsx
|
||||||
|
├── ui/
|
||||||
|
│ ├── hero-section/ # hero только на главной КНВ
|
||||||
|
│ ├── products-section/ # секция препаратов только на главной
|
||||||
|
│ ├── diseases-section/ # секция заболеваний только на главной
|
||||||
|
│ └── doctor-section/ # секция врачей только на главной
|
||||||
|
Каждая секция внутри может использовать shared/ui компоненты:
|
||||||
|
// screens/knv/ui/products-section/products-section.widget.tsx
|
||||||
|
import { Carousel } from 'src/shared/ui/carousel'
|
||||||
|
import { ProductCard } from './ui/product-card' // локальный, пока не переиспользуется
|
||||||
|
Когда локальный компонент начинает использоваться на 2+ страницах — выносим в entities/ или shared/ui.
|
||||||
|
---
|
||||||
|
4. Widgets (src/widgets/)
|
||||||
|
Составные блоки с данными/логикой, которые переиспользуются на 2+ страницах.
|
||||||
|
Критерий: блок с бизнес-логикой + данными используется на нескольких страницах? → widgets/
|
||||||
|
Пример: Слайдер «Популярные препараты» с загрузкой данных из API, который показывается и на главной, и на странице заболевания, и в каталоге:
|
||||||
|
src/widgets/
|
||||||
|
├── popular-products-slider/
|
||||||
|
│ ├── popular-products-slider.widget.tsx # Carousel + ProductCard + useProducts()
|
||||||
|
│ ├── hooks/
|
||||||
|
│ │ └── use-products.hook.ts # запрос данных
|
||||||
|
Не widget: секция «Подобрать врача» которая есть только на главной → screens/knv/ui/
|
||||||
|
---
|
||||||
|
5. Features (src/features/)
|
||||||
|
Пользовательское действие или интерактивный сценарий. Содержит бизнес-логику взаимодействия.
|
||||||
|
Критерий: это действие пользователя (отправить форму, авторизоваться, добавить в корзину)? → features/
|
||||||
|
Примеры:
|
||||||
|
src/features/
|
||||||
|
├── auth/ # авторизация (форма + логика + стор)
|
||||||
|
│ ├── auth.feature.tsx
|
||||||
|
│ ├── hooks/
|
||||||
|
│ │ └── use-auth.hook.ts
|
||||||
|
│ └── stores/
|
||||||
|
│ └── auth.store.ts
|
||||||
|
│
|
||||||
|
├── order-drug/ # заказ препарата (кнопка + модалка + API)
|
||||||
|
│ ├── order-drug.feature.tsx
|
||||||
|
│ └── hooks/
|
||||||
|
│ └── use-order.hook.ts
|
||||||
|
Не feature: отображение карточки препарата без взаимодействия → entities/ или shared/ui
|
||||||
|
---
|
||||||
|
6. Entities (src/entities/)
|
||||||
|
Бизнес-сущность с её отображением и типами. Привязана к домену (препарат, заболевание, врач, пользователь).
|
||||||
|
Критерий: это представление бизнес-объекта, которое переиспользуется в разных контекстах? → entities/
|
||||||
|
Примеры:
|
||||||
|
src/entities/
|
||||||
|
├── product/ # Препарат
|
||||||
|
│ ├── ui/
|
||||||
|
│ │ └── product-card/ # карточка препарата (каталог, слайдеры, поиск)
|
||||||
|
│ ├── types/
|
||||||
|
│ │ └── product.type.ts # { id, name, mnn, indication }
|
||||||
|
│ └── index.ts
|
||||||
|
│
|
||||||
|
├── disease/ # Заболевание
|
||||||
|
│ ├── ui/
|
||||||
|
│ │ └── disease-card/
|
||||||
|
│ ├── types/
|
||||||
|
│ │ └── disease.type.ts
|
||||||
|
│ └── index.ts
|
||||||
|
Отличие от shared/ui: entity-компонент знает о бизнес-домене (принимает Product, а не абстрактные пропсы). shared/ui Button не знает ничего о бизнесе.
|
||||||
|
---
|
||||||
|
7. Shared (src/shared/)
|
||||||
|
Переиспользуемые компоненты, утилиты, стили без бизнес-логики.
|
||||||
|
Критерий: компонент не знает о бизнес-домене, работает с абстрактными данными? → shared/
|
||||||
|
src/shared/
|
||||||
|
├── ui/ # UI-компоненты
|
||||||
|
│ ├── carousel/ # принимает children, не знает о препаратах
|
||||||
|
│ ├── container/
|
||||||
|
│ ├── section/
|
||||||
|
│ └── icon-svg/
|
||||||
|
├── styles/ # CSS-переменные, media
|
||||||
|
│ ├── variables.css
|
||||||
|
│ └── media.css
|
||||||
|
├── sprites/ # SVG-спрайты
|
||||||
|
└── lib/ # утилиты, хелперы
|
||||||
|
---
|
||||||
|
Сводная таблица принятия решений
|
||||||
|
Вопрос Да → Нет ↓
|
||||||
|
Это точка входа маршрута? pages/ ↓
|
||||||
|
Одинаков на всех страницах layout? layouts/{name}/ui/ ↓
|
||||||
|
Используется только на одной странице? screens/{name}/ui/ ↓
|
||||||
|
Составной блок с данными на 2+ страницах? widgets/ ↓
|
||||||
|
Это действие пользователя с логикой? features/ ↓
|
||||||
|
Привязан к бизнес-сущности? entities/ ↓
|
||||||
|
Абстрактный UI без бизнес-логики? shared/ui/ —
|
||||||
Reference in New Issue
Block a user