← Назад к вопросам

Что из себя представляет страница в архитектуре FSD?

2.3 Middle🔥 152 комментариев
#JavaScript Core

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое страница (Page) в архитектуре Feature-Sliced Design (FSD)

В методологии Feature-Sliced Design (FSD) страница (page) — это самостоятельный, полноценный модуль верхнего уровня, который отвечает за композицию фич, виджетов и сущностей в готовый пользовательский интерфейс для определённого маршрута (URL). Страницы находятся на самом верхнем слое архитектуры (apps, pages или app/pages в зависимости от версии FSD) и служат точкой входа для рендеринга конкретного экрана приложения.

Ключевые характеристики страницы в FSD

  • Маршрутизация: Каждая страница напрямую связана с определённым маршрутом (роутом) в приложении. Например, страница ArticlePage будет отвечать за путь /articles/:id.
  • Композиция, а не логика: Основная задача страницы — собрать (скомпоновать) независимые блоки из нижних слоёв (feature, entity, shared). Страница сама по себе не должна содержать сложную бизнес-логику или состояние, выходящее за рамки управления композицией.
  • Минимальная сложность: Идеальная страница — это тонкий слой, который импортирует компоненты, передаёт им необходимые данные (часто через props) и рендерит их в правильном порядке. Вся бизнес-логика вынесена в фичи (features), а переиспользуемая UI-логика — в виджеты (widgets).
  • Публичный API: Страницы являются частью публичного API слоя и могут свободно импортировать модули из любых нижних слоёв (соблюдая правило зависимостей pages -> features -> entities -> shared).

Пример структуры и кода

Рассмотрим структуру проекта и пример кода для страницы просмотра статьи.

Структура папок (по методологии FSD v2):

src/
├── pages/                    # Слой страниц
│   └── article-details/     # Слайс (папка) страницы
│       ├── ui/              # UI-компоненты, специфичные для этой страницы
│       │   └── ArticleDetailsPage.tsx
│       └── index.ts         # Публичный API (реэкспорт)
├── features/                # Слой фич
│   └── add-comment/         # Фича "Добавление комментария"
│       ├── model/           # Логика (стор, эффекты)
│       ├── ui/              # Компоненты фичи
│       └── lib/             # Вспомогательная логика
├── entities/                # Слой сущностей
│   ├── article/             # Сущность "Статья"
│   └── comment/             # Сущность "Комментарий"
├── shared/                  # Переиспользуемый слой
│   ├── ui/                  # UI-кит (Button, Card, etc.)
│   └── api/                 # Инфраструктура API
└── app/                     # Инициализация приложения (роутинг, провайдеры)

Код страницы ArticleDetailsPage:

// src/pages/article-details/ui/ArticleDetailsPage.tsx
import { ArticleDetails } from '@/entities/article';
import { CommentList } from '@/entities/comment';
import { AddCommentForm } from '@/features/add-comment';
import { ArticleRecommendationsList } from '@/features/article-recommendations-list';
import { Page } from '@/shared/ui/page';
import { VStack } from '@/shared/ui/stack';
import { useParams } from 'react-router-dom';

export const ArticleDetailsPage = () => {
    const { id } = useParams<{ id: string }>(); // Получаем ID из URL

    if (!id) {
        return <div>Статья не найдена</div>;
    }

    // Страница только компонует блоки, не содержит своей логики
    return (
        <Page>
            <VStack gap="32" max>
                {/* Сущность: отображение данных статьи */}
                <ArticleDetails articleId={id} />

                {/* Виджет или фича: рекомендации */}
                <ArticleRecommendationsList />

                {/* Фича: форма добавления комментария */}
                <AddCommentForm articleId={id} />

                {/* Сущность: список комментариев */}
                <CommentList articleId={id} />
            </VStack>
        </Page>
    );
};

Роль и преимущества такого подхода

  • Чёткое разделение ответственности: Страница отвечает только за макет и композицию для конкретного маршрута. Это делает её простой для понимания и модификации.
  • Максимальная переиспользуемость: Поскольку вся логика живёт в фичах и сущностях, их можно использовать на разных страницах. Например, AddCommentForm может быть использован и на странице блога, и на странице продукта.
  • Упрощённая навигация и code-splitting: Каждая страница естественным образом становится точкой для ленивой подгрузки (lazy loading). Роутер приложения может динамически импортировать только нужную страницу, что улучшает производительность.
  • Масштабируемость: Добавление нового экрана (маршрута) сводится к созданию новой папки в слое pages и композиции существующих модулей. Это предсказуемо и не приводит к росту энтропии в коде.
  • Ориентация на пользовательские сценарии: Страница — это целостный пользовательский сценарий (просмотр товара, оформление заказа), что совпадает с восприятием продукта менеджерами и дизайнерами, упрощая коммуникацию в команде.

Отличие от других слоёв

  • Страница (Page) vs Фича (Feature): Фича инкапсулирует конкретную возможность пользователя (добавить в корзину, лайкнуть, отфильтровать). Страница же собирает несколько фич в законченный экран. Фича может использоваться на многих страницах.
  • Страница (Page) vs Виджет (Widget): Виджет — это сложный композитный компонент с собственной, часто кросс-фичёвой, логикой отображения (например, Sidebar с навигацией и рекламным баннером). Виджет тоже можно использовать на разных страницах, но страница — это всегда конечный, привязанный к URL экран.

Таким образом, страница в FSD — это конечная точка сборки интерфейса, отвечающая за компоновку независимых, переиспользуемых модулей в соответствии с бизнес-маршрутом, что обеспечивает чистоту, масштабируемость и поддерживаемость кода крупных frontend-приложений.

Что из себя представляет страница в архитектуре FSD? | PrepBro