Маршрутизатор app проти маршрутизатора pages у Next.js
Next.js має дві системи маршрутизації: Pages Router (каталог pages/) та App Router (каталог app/). App Router був представлений у Next.js 13 і став рекомендованим підходом починаючи з версії 13.4.
Основні Відмінності
| Аспект | Pages Router | App Router |
|---|---|---|
| Каталог | pages/ | app/ |
| Компоненти за замовчуванням | Клієнт | Сервер (RSC) |
| Отримання даних | getServerSideProps, getStaticProps | async компоненти з fetch |
| Макети | _app.tsx, _document.tsx | Вкладені layout.tsx |
| UI завантаження | Ручна реалізація | loading.tsx з коробки |
| Помилки | _error.tsx глобально | error.tsx на маршрут |
| Стрімінг | Ні | Так, через Suspense |
| Серверні дії | Ні | Так |
Pages Router
У Pages Router кожен файл у каталозі pages/ автоматично стає маршрутом. Дані завантажуються через спеціальні функції:
// pages/problems/index.tsx
export async function getServerSideProps() {
const res = await fetch('https://api.itlead.org/problems')
const problems = await res.json()
return { props: { problems } }
}
export default function ProblemsPage({ problems }) {
return (
<ul>
{problems.map(p => (
<li key={p.id}>{p.name}</li>
))}
</ul>
)
}Макети реалізуються через _app.tsx, який обгортає всі сторінки:
// pages/_app.tsx
export default function App({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}App Router
У App Router компоненти за замовчуванням є серверними. Дані завантажуються безпосередньо в компоненті:
// app/problems/page.tsx
import { db } from '@/lib/db'
export default async function ProblemsPage() {
const problems = await db.problem.findMany()
return (
<ul>
{problems.map(p => (
<li key={p.id}>{p.name}</li>
))}
</ul>
)
}Макети вкладені і зберігають стан під час навігації:
// app/problems/layout.tsx
export default function ProblemsLayout({
children
}: {
children: React.ReactNode
}) {
return (
<div className="problems-container">
<Sidebar />
<main>{children}</main>
</div>
)
}Що надає App Router
Серверні компоненти за замовчуванням
Код серверного компонента не потрапляє в пакет клієнта. Важкі залежності залишаються на сервері:
// app/docs/[slug]/page.tsx
import { MDXRemote } from 'next-mdx-remote/rsc'
import { getDocBySlug } from '@/lib/docs'
export default async function DocPage({
params
}: {
params: { slug: string }
}) {
const doc = await getDocBySlug(params.slug)
return <MDXRemote source={doc.content} />
}Бібліотека next-mdx-remote не надсилається клієнту. Саме так статті рендеряться на IT Lead.
Стрімінг
App Router підтримує стрімінг через файли loading.tsx та React Suspense:
// app/dashboard/loading.tsx
export default function Loading() {
return <DashboardSkeleton />
}Користувач бачить скелетон відразу, поки дані завантажуються поступово.
Вкладені макети
Pages Router має один глобальний макет. У App Router макети вкладені і не перерендерюються під час навігації між дочірніми сторінками:
-
app
-
layout.tsx
-
docs
-
layout.tsx
-
page.tsx
-
[slug]
-
page.tsx
Коли обирати який
App Router підходить для нових проектів. Це рекомендований підхід, який отримує всі нові функції.
Pages Router продовжує підтримуватися. Якщо проект вже побудований на Pages Router і працює добре, міграція не є обов'язковою.
Порада для співбесіди:
Обидва маршрутизатори можуть співіснувати в одному проекті. Це дозволяє поступову міграцію, один маршрут за раз.
Корисні Ресурси
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.