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

Как устроен App Router?

2.0 Middle🔥 131 комментариев
#Архитектура и паттерны

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

Как устроен App Router в Next.js

Основная концепция

App Router — это система маршрутизации в Next.js 13+, которая заменила Pages Router. Она использует файловую систему для определения маршрутов, где структура папок прямо соответствует URL структуре приложения. Каждая папка в директории app/ представляет собой segment (сегмент) маршрута.

Структура и базовые компоненты

В App Router используется несколько ключевых файлов:

  • page.tsx — основной компонент, отображается при обращении к маршруту
  • layout.tsx — оборачивает все дочерние страницы, сохраняет состояние
  • error.tsx — обработчик ошибок для boundary
  • loading.tsx — компонент для отображения на время загрузки
  • not-found.tsx — кастомная 404 страница
  • route.ts — API маршруты (GET, POST, PUT, DELETE)

Пример структуры

app/
├── layout.tsx          # Root layout
├── page.tsx            # /
├── about/
│   └── page.tsx        # /about
├── products/
│   ├── layout.tsx      # Layout для /products и подстраниц
│   ├── page.tsx        # /products
│   └── [id]/
│       └── page.tsx    # /products/123
└── api/
    └── users/
        └── route.ts    # API endpoint POST /api/users

Динамические маршруты

Для создания динамических сегментов используются квадратные скобки:

// app/products/[id]/page.tsx
interface Props {
  params: Promise<{ id: string }>; // Next.js 15+ требует Promise
}

export default async function ProductPage({ params }: Props) {
  const { id } = await params;
  return <div>Product: {id}</div>;
}

Catch-all маршруты

// app/docs/[[...slug]]/page.tsx
interface Props {
  params: Promise<{ slug?: string[] }>;
}

export default async function DocsPage({ params }: Props) {
  const { slug } = await params;
  // /docs -> slug undefined
  // /docs/guide/setup -> slug = ['guide', 'setup']
  return <div>Docs: {slug?.join('/')}</div>;
}

Layouts — иерархия и переиспользование

Layout — компонент, который оборачивает дочерние page и сохраняет состояние при навигации:

// app/layout.tsx (Root Layout)
export const metadata = {
  title: 'My App',
  description: 'Generated by create next app',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ru">
      <body>
        <Header />
        {children}
        <Footer />
      </body>
    </html>
  );
}

// app/dashboard/layout.tsx (Segment Layout)
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div>
      <Sidebar />
      <main>{children}</main>
    </div>
  );
}

Server Components и Client Components

По умолчанию все компоненты в App Router — Server Components, что дает преимущества:

// app/products/page.tsx — Server Component по умолчанию
// Может напрямую обращаться к БД
export default async function ProductsPage() {
  const products = await db.query('SELECT * FROM products');
  return (
    <div>
      {products.map(p => (
        <ProductCard key={p.id} product={p} />
      ))}
    </div>
  );
}

// app/components/filters.tsx — Client Component
'use client';

import { useState } from 'react';

export function Filters() {
  const [filters, setFilters] = useState({});
  return <div>...</div>;
}

Навигация и Link

Для навигации используется компонент Link из Next.js:

import Link from 'next/link';

export function Navigation() {
  return (
    <nav>
      <Link href="/">Home</Link>
      <Link href="/about">About</Link>
      <Link href={`/products/${id}`}>Product</Link>
    </nav>
  );
}

Для программной навигации используется useRouter:

'use client';

import { useRouter } from 'next/navigation'; // ! navigation, не router

export function GoBack() {
  const router = useRouter();
  
  return (
    <button onClick={() => router.push('/dashboard')}>
      Вернуться
    </button>
  );
}

Преимущества App Router

  • Server Components — автоматический SSR, безопасность, прямой доступ к БД
  • Вложенные layouts — переиспользование UI, сохранение состояния
  • Колокализация — файлы компонентов и стилей рядом
  • Улучшенная обработка ошибок — error.tsx и not-found.tsx
  • Loading states — loading.tsx для Suspense
  • Параллельные маршруты — одновременная загрузка нескольких сегментов

Отличие от Pages Router

В старом Pages Router использовались _app.js и _document.js для глобальной конфигурации. В App Router это заменено на layout.tsx в корне app/ директории, что более гибко и понятно.