Next.js 13: Page Router vs App Router 全面对比
Next.js 作为一个强大的 React 框架,为开发者提供了两种路由系统:App Router 和 Pages Router。这两种路由系统各有特色,适用于不同的场景。App Router 是 Next.js 13 引入的新路由系统。本文将深入探讨 Page Router 和 Next.js 13+ 的 App Router 的详细对比,包括目录结构、API 处理、数据获取、渲染模式、组件行为等多个方面。
Next.js Page Router vs. App Router 详细对比
1. 目录结构
Page Router(13 之前)
/pages
├── index.tsx # 主页
├── about.tsx # 关于页
├── api
│ ├── user.ts # API 路由
│ ├── auth.ts # API 路由
所有页面 都放在
/pages
目录下API 路由 放在
/pages/api/
目录下文件名就是路由路径,如
/pages/about.tsx
访问/about
App Router(13+)
/app
├── layout.tsx # 根布局(全局生效)
├── page.tsx # 主页
├── about
│ ├── page.tsx # 关于页
│ ├── loading.tsx # 加载状态
│ ├── error.tsx # 错误状态
├── api
│ ├── user
│ │ ├── route.ts # API 路由
│ ├── auth
│ │ ├── route.ts # API 路由
所有页面 放在
/app
目录下每个页面都需要
page.tsx
文件API 路由必须用
route.ts
文件布局
layout.tsx
可继承
2. API 路由
Page Router
// pages/api/user.ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(200).json({ message: "Hello, world!" });
}
直接导出
handler(req, res)
只支持
GET/POST
等传统 HTTP 方法所有 API 文件放
/pages/api/
App Router
// app/api/user/route.ts
import { NextResponse } from 'next/server';
export async function GET() {
return NextResponse.json({ message: "Hello, world!" });
}
export async function POST(req: Request) {
const body = await req.json();
return NextResponse.json({ data: body });
}
必须创建
route.ts
文件使用
Request
和NextResponse
处理请求支持 RESTful API 方法(GET、POST、PUT、DELETE)
3. 数据获取(服务器端渲染)
Page Router
export async function getServerSideProps() {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return { props: { data } };
}
export default function HomePage({ data }) {
return <div>{data.message}</div>;
}
使用
getServerSideProps
进行服务器端渲染代码只能运行在服务端,客户端看不到
App Router
export default async function HomePage() {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return <div>{data.message}</div>;
}
默认服务器端渲染(SSR)
不需要
getServerSideProps
,直接await fetch
即可可以结合
fetch()
进行缓存优化
4. 组件行为
Page Router
默认所有组件是 客户端组件
只有
getServerSideProps
和getStaticProps
运行在服务器上
App Router
默认是服务器组件(Server Component)
如果要使用
useState
、useEffect
,必须加"use client"
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
5. 路由导航
Page Router
import { useRouter } from 'next/router';
const router = useRouter();
console.log(router.pathname);
使用
useRouter()
获取当前路由
App Router
import { usePathname } from 'next/navigation';
const pathname = usePathname();
console.log(pathname);
必须用
usePathname()
获取当前路由
6. SEO 处理
Page Router
import Head from 'next/head';
export default function HomePage() {
return (
<>
<Head>
<title>我的网站</title>
<meta name="description" content="一个很棒的网站" />
</Head>
<h1>欢迎来到我的网站</h1>
</>
);
}
使用
<Head>
组件定义 SEO 标签
App Router
import { Metadata } from 'next';
export const metadata: Metadata = {
title: "我的网站",
description: "一个很棒的网站",
};
export default function HomePage() {
return <h1>欢迎来到我的网站</h1>;
}
使用
export const metadata
直接定义 SEO 标签
7. 静态生成(SSG)
Page Router
export async function getStaticProps() {
const data = await fetchData();
return { props: { data } };
}
需要
getStaticProps()
生成静态页面
App Router
export default async function Page() {
const data = await fetchData();
return <div>{data}</div>;
}
默认支持 SSG,静态生成更自然
8. 优缺点总结
总结
小型项目:使用 Page Router,简单、易上手
大型项目:使用 App Router,支持更强的性能优化
App Router 让服务器端渲染更直观、API 处理更规范、组件默认是服务器组件,减少不必要的 JS 加载,提高性能