Комментарии (3)
Ответ сгенерирован нейросетью и может содержать ошибки
Старый Pages Router в Next.js: как он работал
Next.js раньше использовал Pages Router (до версии 13), который основывался на file-system routing. Хотя это была отличная система, в Next.js 13+ её заменили на более мощный App Router. Но понимание Pages Router остаётся важным для legacy проектов и собеседований.
File-system Routing
Pages Router работал по простому принципу: структура файлов автоматически создавала роуты.
pages/
index.js -> /
about.js -> /about
products.js -> /products
products/
[id].js -> /products/:id (динамический роут)
[...slug].js -> /products/* (catch-all роут)
api/
users.js -> /api/users (API endpoint)
users/[id].js -> /api/users/:id
Базовая страница в Pages Router
// pages/index.js (главная страница)
export default function Home() {
return <h1>Добро пожаловать!</h1>;
}
// pages/about.js (страница /about)
export default function About() {
return <h1>О нас</h1>;
}
Динамические роуты
Квадратные скобки создавали динамические параметры:
// pages/posts/[id].js
import { useRouter } from 'next/router';
export default function Post() {
const router = useRouter();
const { id } = router.query; // Получить параметр из URL
return <h1>Post {id}</h1>;
}
// Возможные URL:
// /posts/1
// /posts/hello
// /posts/123-my-post
Catch-all роуты
Три точки [...param] ловили все оставшиеся сегменты:
// pages/docs/[...slug].js
import { useRouter } from 'next/router';
export default function Docs() {
const router = useRouter();
const { slug } = router.query; // массив сегментов
return <h1>Docs: {slug?.join(' / ')}</h1>;
}
// /docs/getting-started -> slug = ['getting-started']
// /docs/api/users -> slug = ['api', 'users']
// /docs/guide/setup/steps -> slug = ['guide', 'setup', 'steps']
getStaticProps и getServerSideProps
Pages Router использовал эти функции для генерации страниц:
// pages/posts/[id].js
// Static Generation (SSG)
export async function getStaticProps({ params }) {
const post = await fetchPost(params.id);
return {
props: { post },
revalidate: 60, // ISR: перегенерировать каждые 60 секунд
};
}
// Нужно указать какие роуты pre-render
export async function getStaticPaths() {
return {
paths: [
{ params: { id: '1' } },
{ params: { id: '2' } },
],
fallback: 'blocking', // или false, или true
};
}
export default function Post({ post }) {
return <h1>{post.title}</h1>;
}
Server-Side Rendering:
// pages/user-profile.js
export async function getServerSideProps(context) {
const { req, res } = context;
// Выполняется на каждом запросе (медленнее, но свежие данные)
const user = await fetchUser(req.headers.cookie);
if (!user) {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
return {
props: { user },
};
}
export default function Profile({ user }) {
return <h1>{user.name}</h1>;
}
API Routes
API создавались в папке pages/api:
// pages/api/users.js
export default function handler(req, res) {
if (req.method === 'GET') {
res.status(200).json({ users: [] });
} else if (req.method === 'POST') {
res.status(201).json({ created: true });
} else {
res.status(405).json({ error: 'Method Not Allowed' });
}
}
// pages/api/users/[id].js
export default function handler(req, res) {
const { id } = req.query;
if (req.method === 'GET') {
res.status(200).json({ id, user: 'John' });
}
}
Навигация в Pages Router
import Link from 'next/link';
import { useRouter } from 'next/router';
export default function Navigation() {
const router = useRouter();
return (
<>
{/* Link компонент для навигации */}
<Link href="/about">
<a>О нас</a>
</Link>
{/* Программная навигация */}
<button onClick={() => router.push('/dashboard')}>
Перейти в панель
</button>
{/* Замена в истории вместо push */}
<button onClick={() => router.replace('/home')}>
Заменить страницу
</button>
</>
);
}
Middleware (Pages Router)
Простое middleware выполнялось на каждом запросе:
// middleware.js (в корне проекта)
import { NextResponse } from 'next/server';
export function middleware(request) {
// Редирект неавторизованных пользователей
if (!request.cookies.get('auth')) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*'], // Применить только к /dashboard
};
Сравнение Pages Router и App Router
Pages Router (старый) App Router (новый)
====================================
pages/ app/
Dynamic: [id].js Dynamic: [id]/page.js
API Routes: pages/api/ API Routes: app/api/ (route.js)
getStaticProps generateStaticParams
getServerSideProps нет прямого аналога
useRouter useRouter (из next/navigation)
Link с <a> Link без <a> тега
Пример: полная старая структура
// pages/index.js
export default function Home() {
return <h1>Главная</h1>;
}
// pages/products/[id].js
export async function getStaticProps({ params }) {
const product = await fetch(`/api/products/${params.id}`);
return { props: { product }, revalidate: 60 };
}
export async function getStaticPaths() {
return {
paths: [{ params: { id: '1' } }],
fallback: 'blocking',
};
}
export default function Product({ product }) {
return <h1>{product.name}</h1>;
}
// pages/api/products/[id].js
export default function handler(req, res) {
const { id } = req.query;
res.json({ id, name: 'Product ' + id });
}
Почему заменили на App Router
- Server Components — лучшая производительность
- Layouts — вложенные слои без повторов кода
- Более гибкий routing — не привязан к файловой структуре
- Единая система — API и страницы в одной папке
- Лучше для Large Scale приложений
Pages Router отличался простотой и intuitiveness, но App Router более мощный для больших проектов. На собеседованиях могут спросить, как работал Pages Router, чтобы оценить твой опыт с Next.js эволюцией.