Страницы и макеты
Рекомендуем прочитать разделы Основы маршрутизации и Определение маршрутов перед продолжением.
App Router в Next.js 13 представил новые соглашения по файлам для удобного создания страниц, общих макетов и шаблонов. Это руководство покажет, как использовать эти специальные файлы в вашем приложении Next.js.
Страницы
Страница — это пользовательский интерфейс, уникальный для маршрута. Вы можете определить страницы, экспортируя компонент из файла page.js
. Используйте вложенные папки для определения маршрута и файл page.js
, чтобы сделать маршрут общедоступным.
Создайте свою первую страницу, добавив файл page.js
в директорию app
:

// `app/page.tsx` — это UI для URL `/`
export default function Page() {
return <h1>Привет, домашняя страница!</h1>
}
// `app/page.js` — это UI для URL `/`
export default function Page() {
return <h1>Привет, домашняя страница!</h1>
}
// `app/dashboard/page.tsx` — это UI для URL `/dashboard`
export default function Page() {
return <h1>Привет, страница Dashboard!</h1>
}
// `app/dashboard/page.js` — это UI для URL `/dashboard`
export default function Page() {
return <h1>Привет, страница Dashboard!</h1>
}
Полезно знать:
- Страница всегда является листом поддерева маршрутов.
- Для страниц можно использовать расширения файлов
.js
,.jsx
или.tsx
.- Файл
page.js
обязателен для общедоступности сегмента маршрута.- Страницы по умолчанию являются серверными компонентами (Server Components), но могут быть настроены как клиентские компоненты (Client Components).
- Страницы могут получать данные. Подробнее см. в разделе Получение данных.
Макеты
Макет — это пользовательский интерфейс, общий для нескольких страниц. При навигации макеты сохраняют состояние, остаются интерактивными и не перерендериваются. Макеты также могут быть вложенными.
Вы можете определить макет, экспортируя React-компонент по умолчанию из файла layout.js
. Компонент должен принимать проп children
, который будет заполнен дочерним макетом (если он существует) или страницей во время рендеринга.

export default function DashboardLayout({
children, // будет страницей или вложенным макетом
}: {
children: React.ReactNode
}) {
return (
<section>
{/* Разместите общий UI здесь, например, шапку или боковую панель */}
<nav></nav>
{children}
</section>
)
}
export default function DashboardLayout({
children, // будет страницей или вложенным макетом
}) {
return (
<section>
{/* Разместите общий UI здесь, например, шапку или боковую панель */}
<nav></nav>
{children}
</section>
)
}
Полезно знать:
- Самый верхний макет называется Корневым макетом (Root Layout). Этот обязательный макет используется всеми страницами приложения. Корневой макет должен содержать теги
html
иbody
.- Любой сегмент маршрута может опционально определить свой собственный макет. Эти макеты будут общими для всех страниц в этом сегменте.
- Макеты в маршруте по умолчанию вложены. Каждый родительский макет оборачивает дочерние макеты с помощью пропа
children
в React.- Вы можете использовать Группы маршрутов (Route Groups) для включения или исключения определенных сегментов маршрута из общих макетов.
- Макеты по умолчанию являются серверными компонентами (Server Components), но могут быть настроены как клиентские компоненты (Client Components).
- Макеты могут получать данные. Подробнее см. в разделе Получение данных.
- Передача данных между родительским макетом и его дочерними элементами невозможна. Однако вы можете получать одни и те же данные в маршруте несколько раз, и React автоматически устранит дублирование запросов без ущерба для производительности.
- Макеты не имеют доступа к сегментам маршрута ниже себя. Для доступа ко всем сегментам маршрута можно использовать
useSelectedLayoutSegment
илиuseSelectedLayoutSegments
в клиентском компоненте.- Для макетов можно использовать расширения файлов
.js
,.jsx
или.tsx
.- В одной папке могут быть определены файлы
layout.js
иpage.js
. Макет будет оборачивать страницу.
Корневой макет (обязательный)
Корневой макет определяется на верхнем уровне директории app
и применяется ко всем маршрутам. Этот макет позволяет изменять исходный HTML, возвращаемый сервером.
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Полезно знать:
- Директория
app
обязательно должна включать корневой макет.- Корневой макет должен определять теги
<html>
и<body>
, так как Next.js не создает их автоматически.- Вы можете использовать встроенную поддержку SEO для управления HTML-элементами
<head>
, например, элементом<title>
.- Вы можете использовать группы маршрутов для создания нескольких корневых макетов. См. пример здесь.
- Корневой макет по умолчанию является серверным компонентом (Server Component) и не может быть настроен как клиентский компонент (Client Component).
Миграция из директории
pages
: Корневой макет заменяет файлы_app.js
и_document.js
. См. руководство по миграции.
Вложенные макеты
Макеты, определенные внутри папки (например, app/dashboard/layout.js
), применяются к определенным сегментам маршрута (например, acme.com/dashboard
) и рендерятся, когда эти сегменты активны. По умолчанию макеты в иерархии файлов вложены, то есть они оборачивают дочерние макеты через проп children
.

export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
export default function DashboardLayout({ children }) {
return <section>{children}</section>
}
Полезно знать:
- Только корневой макет может содержать теги
<html>
и<body>
.
Если объединить два макета выше, корневой макет (app/layout.js
) будет оборачивать макет дашборда (app/dashboard/layout.js
), который, в свою очередь, будет оборачивать сегменты маршрута внутри app/dashboard/*
.
Два макета будут вложены следующим образом:

Вы можете использовать Группы маршрутов (Route Groups) для включения или исключения определенных сегментов маршрута из общих макетов.
Шаблоны
Шаблоны похожи на макеты тем, что они оборачивают каждый дочерний макет или страницу. В отличие от макетов, которые сохраняются между маршрутами и поддерживают состояние, шаблоны создают новый экземпляр для каждого из своих дочерних элементов при навигации. Это означает, что при переходе между маршрутами, использующими один шаблон, монтируется новый экземпляр компонента, пересоздаются DOM-элементы, состояние не сохраняется, и эффекты синхронизируются заново.
В некоторых случаях такое поведение может быть полезно, и шаблоны будут более подходящим выбором, чем макеты. Например:
- Функции, зависящие от
useEffect
(например, логирование просмотров страниц) иuseState
(например, форма обратной связи для каждой страницы). - Для изменения поведения фреймворка по умолчанию. Например, Suspense Boundaries внутри макетов показывают fallback только при первой загрузке макета, а не при переключении страниц. Для шаблонов fallback показывается при каждой навигации.
Шаблон можно определить, экспортируя React-компонент по умолчанию из файла template.js
. Компонент должен принимать проп children
.

export default function Template({ children }: { children: React.ReactNode }) {
return <div>{children}</div>
}
export default function Template({ children }) {
return <div>{children}</div>
}
С точки зрения вложенности, template.js
рендерится между макетом и его дочерними элементами. Вот упрощенный вывод:
<Layout>
{/* Обратите внимание, что шаблону присваивается уникальный ключ. */}
<Template key={routeParam}>{children}</Template>
</Layout>
Изменение <head>
В директории app
вы можете изменять HTML-элементы <head>
, такие как title
и meta
, с помощью встроенной поддержки SEO.
Метаданные можно определить, экспортируя объект metadata
или функцию generateMetadata
в файле layout.js
или page.js
.
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
export const metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
Полезно знать: Не следует вручную добавлять теги
<head>
, такие как<title>
и<meta>
, в корневые макеты. Вместо этого используйте Metadata API, который автоматически обрабатывает сложные требования, такие как потоковая передача и устранение дублирования элементов<head>
.
Узнайте больше о доступных опциях метаданных в справочнике API.