Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Что находится в слое Shared в методологии Feature-Sliced Design (FSD)?
Shared (Общий) слой — это фундаментальный элемент архитектуры Feature-Sliced Design (FSD), предназначенный для хранения переиспользуемых модулей, которые не привязаны к конкретной бизнес-логике приложения. Его главная цель — обеспечить единообразие и исключить дублирование кода по всему проекту. В отличие от слоёв App, Pages, Widgets, Features и Entities, которые организованы по принципу "близости к пользователю" или бизнес-сущностям, слой Shared служит технической инфраструктурой, поддерживающей работу всех остальных слоёв. Он является самым низкоуровневым в иерархии FSD и не должен зависеть ни от одного вышестоящего слоя.
Ключевые составляющие слоя Shared
Обычно в этот слой включают следующие категории кода:
1. UI-компоненты (UI-Kit)
Базовые, примитивные компоненты интерфейса, которые не содержат бизнес-логики. Они являются строительными блоками для более сложных компонентов в вышележащих слоях.
- Примеры: Кнопки (
Button), поля ввода (Input), модальные окна (Modal), заголовки (Typography), иконки (Icon). - Критерий: Компонент должен быть максимально абстрактным и переиспользуемым в различных контекстах. Например, кнопка принимает
children,onClickиvariant, но не знает о "добавлении товара в корзину".
// shared/ui/Button/Button.tsx
import { ButtonHTMLAttributes, ReactNode } from 'react';
import cls from './Button.module.scss';
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: ReactNode;
variant?: 'primary' | 'secondary' | 'outline';
}
export const Button = ({ children, variant = 'primary', ...props }: ButtonProps) => {
return (
<button className={`${cls.button} ${cls[variant]}`} {...props}>
{children}
</button>
);
};
2. Инфраструктурные утилиты и хелперы
Функции и классы для работы с данными, форматирования, валидации и других общих задач.
- Примеры: Форматирование даты (
formatDate), валидация email (isValidEmail), функции для работы с массивами/объектами (debounce,throttle), генерация уникальных ID.
// shared/lib/format/formatDate.ts
export const formatDate = (date: Date, locale: string = 'ru-RU'): string => {
return new Intl.DateTimeFormat(locale, {
year: 'numeric',
month: 'long',
day: 'numeric',
}).format(date);
};
3. Конфигурация и константы
Глобальные настройки и неизменяемые значения, используемые в разных частях приложения.
- Примеры: Конфигурация API (
API_URL), ключи для локального хранилища (LOCAL_STORAGE_KEYS), текстовые константы (DEFAULT_PAGE_SIZE), настройки темы (цвета, отступы).
// shared/config/consts.ts
export const API_URL = process.env.REACT_APP_API_URL || 'http://localhost:3000/api';
export const DEFAULT_PAGE_SIZE = 20;
export const LOCAL_STORAGE_KEYS = {
ACCESS_TOKEN: 'access_token',
THEME: 'app_theme',
} as const;
4. Типы и интерфейсы (для TypeScript)
Общие типы данных, которые используются в нескольких слоях или фичах.
- Примеры: Базовые типы (
Maybe<T>,PaginatedResponse<T>), интерфейсы для общих DTO (Data Transfer Object), утилитарные типы (ValueOf,Keys).
// shared/types/api.ts
export type PaginatedResponse<T> = {
items: T[];
total: number;
page: number;
limit: number;
};
export type ApiError = {
message: string;
code: number;
};
5. API-инстансы и HTTP-клиенты
Настройка базового клиента для сетевых запросов (например, с помощью axios или fetch).
- Примеры: Экземпляр
axiosс интерцепторами для добавления токенов, обработки ошибок, логирования.
// shared/api/apiInstance.ts
import axios from 'axios';
import { API_URL } from '../config/consts';
export const apiInstance = axios.create({
baseURL: API_URL,
timeout: 10000,
});
apiInstance.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
6. Управление состоянием (глобальные сторы)
Только в случае, если стор является глобальным и обслуживает технические аспекты, не связанные с бизнес-доменом.
- Примеры: Стор для управления темой приложения (
ThemeStore), стор для уведомлений/тостов (NotificationStore), стор для загрузки данных приложения (AppLoadStore). Важно: Сторы, относящиеся к бизнес-сущностям (например,UserStore,CartStore), должны находиться в слоеEntities.
Принципы и ограничения слоя Shared
- Запрет на внутренние импорты "сверху": Модули внутри
Sharedне могут импортировать что-либо из слоёвEntities,Features,Widgets,PagesилиApp. Это гарантирует его независимость и переиспользуемость. - Минимизация бизнес-логики: Код в
Sharedдолжен быть максимально агностичным к предметной области. Если модуль начинает знать о "пользователях", "заказах" или "платежах", это верный признак, что его нужно переместить в слойEntitiesилиFeatures. - Высокая степень переиспользования: Если некий код используется только в одном
Featureили на однойPage, он, скорее всего, не принадлежитShared. Его следует разместить ближе к месту использования, соблюдая принцип инверсии зависимостей. - Структура внутри слоя: Сам слой
Sharedтакже может быть структурирован по технологическому признаку (например,ui/,lib/,api/,config/,types/), а не по бизнес-признаку.
Итог
Таким образом, слой Shared в FSD — это технологический фундамент приложения, его "стандартная библиотека". Он содержит всё, что можно вынести за рамки бизнес-требований: от базовых кнопок и утилит форматирования до конфигурации API и глобальных типов. Его правильная организация критически важна для поддержания чистоты архитектуры, снижения связанности между модулями и обеспечения долгосрочной масштабируемости проекта.