App Router и страницы
App Router — современный роутинг Next.js. Файлы в app/ автоматически становятся маршрутами.
Базовые файлы
page.tsx— страница (публичный маршрут)layout.tsx— общий layoutloading.tsx— состояние загрузкиerror.tsx— обработка ошибокnot-found.tsx— 404route.ts— API-роут
Простая страница
app/page.tsx:
export default function Home() {
return <h1>Главная</h1>;
}
app/about/page.tsx:
export default function About() {
return <h1>О нас</h1>;
}
URL: /about.
Вложенные папки
app/
├── page.tsx → /
├── about/
│ └── page.tsx → /about
├── blog/
│ ├── page.tsx → /blog
│ └── post/
│ └── page.tsx → /blog/post
Папка = сегмент URL. page.tsx делает сегмент доступным.
Динамические маршруты
app/posts/[id]/page.tsx:
export default async function Post({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
return <h1>Пост {id}</h1>;
}
URL: /posts/1, /posts/2, /posts/hello.
Catch-all
app/docs/[...slug]/page.tsx:
export default async function Docs({ params }: { params: Promise<{ slug: string[] }> }) {
const { slug } = await params;
return <p>Путь: {slug.join('/')}</p>;
}
Ловит /docs/a, /docs/a/b, /docs/a/b/c.
Опциональный catch-all
[[...slug]] — ловит и /docs без сегментов:
app/docs/[[...slug]]/page.tsx
Группы маршрутов
Папки в скобках не попадают в URL:
app/
├── (marketing)/
│ ├── about/page.tsx → /about
│ └── contact/page.tsx → /contact
└── (shop)/
├── cart/page.tsx → /cart
└── checkout/page.tsx → /checkout
Используются для группировки по layout или логике.
Link
import Link from 'next/link';
<Link href="/about">О нас</Link>
<Link href={`/posts/${post.id}`}>{post.title}</Link>
Link делает клиентскую навигацию и предзагрузку.
useRouter
Программная навигация:
'use client';
import { useRouter } from 'next/navigation';
export default function Button() {
const router = useRouter();
return <button onClick={() => router.push('/about')}>О нас</button>;
}
Методы: push, replace, back, forward, refresh, prefetch.
usePathname и useSearchParams
'use client';
import { usePathname, useSearchParams } from 'next/navigation';
const pathname = usePathname();
const searchParams = useSearchParams();
const page = searchParams.get('page');
Метаданные
export const metadata = {
title: 'О нас',
description: 'Описание страницы',
};
Динамические:
export async function generateMetadata({ params }) {
const { id } = await params;
const post = await getPost(id);
return { title: post.title };
}
Итоги
- Файлы в
app/— маршруты page.tsx— страница[id]— динамический сегмент[...slug]— catch-all(group)— группа без URLLinkдля навигацииmetadataдля SEO