--- title: Файлы роутинга description: Как работать со страницами и другими файлами роутинга Next.js App Router. --- # Файлы роутинга Как работать со страницами и другими файлами роутинга Next.js App Router. ## Назначение `src/app/**` — точка входа приложения и слой файлового роутинга Next.js. Файлы роутинга не реализуют интерфейс. Они описывают маршрут: читают параметры, получают данные первого рендера, подготавливают кеш или состояние и передают результат в screen. Границы слоя описаны в [Архитектура → Слои → App](../basics/architecture/reference/layers.md#слой-app). ## Граница ответственности | Область | Где живёт | |---|---| | Файлы маршрутов (`page.tsx`, `layout.tsx`, `loading.tsx`, `error.tsx`, `not-found.tsx`) | `src/app/**` | | Параметры маршрута, `metadata`, `redirect()`, `notFound()` | `src/app/**` | | Серверные запросы для первого рендера | `src/app/**`, через готовые клиенты и сервисы нижних слоёв | | Прогрев SWR-кеша, начальное состояние, подключение провайдеров | `src/app/**`, только через готовые обёртки из нижних слоёв | | UI страницы | `screens/` | | Каркас страницы: header, footer, sidebar | `layouts/` | | Провайдеры, сторы, хуки, API-клиенты, сервисы | нижние слои (`screens/`, `business/`, `infrastructure/`, `shared/`) | | CSS Modules и стили компонентов | рядом с компонентами, не в `src/app/**` | ## Что можно делать в `page.tsx` - Экспортировать `metadata` или `generateMetadata`. - Читать `params` и `searchParams`. - Нормализовать и валидировать параметры маршрута. - Делать серверные запросы для первого рендера через готовые клиенты или сервисы. - Вызывать `redirect()` и `notFound()`. - Готовить начальные данные для screen. - Готовить SWR `fallback` и передавать его в готовый провайдер. - Подключать готовый провайдер стора страницы и передавать начальное состояние. - Рендерить screen или композицию из готовых обёрток и screen. ## Что запрещено - Писать UI-разметку страницы прямо в файле роутинга. - Создавать локальные компоненты внутри `src/app/**`. - Добавлять CSS Modules, стили компонентов, `components/`, `styles/`, `hooks/`, `stores/`, `services/` внутри `src/app/**`. - Реализовывать провайдеры, сторы, хуки, API-клиенты или сервисы в файлах роутинга. - Размещать бизнес-логику, мапперы и правила предметной области в файлах роутинга. - Вызывать `useSWR` и доменные клиентские хуки в файлах роутинга. ## Страницы Страница объявляется через `export default function`. Для серверных запросов используется `async function`. ```tsx import type { Metadata } from 'next' import { ProfileScreen } from 'screens/profile' export const metadata: Metadata = { title: 'Профиль', description: 'Страница профиля пользователя', } type ProfilePageProps = { params: Promise<{ id: string }> } export default async function ProfilePage({ params }: ProfilePageProps) { const { id } = await params return } ``` ## Данные первого рендера Если данные нужны до первого рендера, `page.tsx` получает их на сервере и передаёт в screen. Сам запрос выполняется через готовый клиент или сервис нижнего слоя. ```tsx import { notFound } from 'next/navigation' import { userApi } from 'infrastructure/backend-api' import { UserScreen } from 'screens/user' type UserPageProps = { params: Promise<{ id: string }> } export default async function UserPage({ params }: UserPageProps) { const { id } = await params const user = await userApi.users.get(id) if (!user) { notFound() } return } ``` Если данные нужны нескольким клиентским SWR-хукам, файл роутинга может обернуть дерево в `SWRConfig` и передать `fallback`. Запросы стартуют на сервере, а клиентские хуки получают данные из кеша. Ключи `fallback` должны совпадать с ключами внутри GET-хуков REST-клиента. Для array-key используется `unstable_serialize`. ```tsx import type { ReactNode } from 'react' import { SWRConfig, unstable_serialize } from 'swr' import { backendApi, getCurrentUserKey, getPostListKey, } from 'infrastructure/backend-api' type FeedLayoutProps = { children: ReactNode } export default async function FeedLayout({ children }: FeedLayoutProps) { const userPromise = backendApi.user.getCurrent() const postsPromise = backendApi.posts.list() return ( {children} ) } ``` Подробнее о стратегиях запросов и начальных данных для клиентских хуков: [REST → Стратегии получения данных](../data/rest/strategies/index.md), [REST → Начальные данные для клиентских хуков](../data/rest/strategies/client-hooks-initial-data.md). ## Инициализация состояния Файл роутинга может подключить готовый провайдер стора страницы, если состояние зависит от маршрута или данных первого рендера. Реализация стора и провайдера не размещается в `src/app/**`. ```tsx import { ProfileScreen, ProfileStoreProvider } from 'screens/profile' type ProfilePageProps = { params: Promise<{ id: string }> } export default async function ProfilePage({ params }: ProfilePageProps) { const { id } = await params return ( ) } ``` ## Layout `layout.tsx` подключает готовую инициализацию приложения: глобальные стили, провайдеры и верхнеуровневые обёртки из нижних слоёв. Вёрстка layout-каркаса выносится в слой `layouts/`. Реализация провайдеров, стилей и UI не размещается в `app/`. ## Error и Not Found `error.tsx` и `not-found.tsx` делегируют разметку готовым screen или widget. В файле роутинга остаётся только адаптация API Next.js к пропсам нижнего слоя. ```tsx 'use client' import { ErrorScreen } from 'screens/error' type ErrorPageProps = { error: Error & { digest?: string } reset: () => void } const ErrorPage = ({ error, reset }: ErrorPageProps) => { return } export default ErrorPage ```