6月2日 23:14
Next.js Pages Router 和 App Router 有什么区别?该不该迁移?
Pages Router 是 Next.js 的原始路由系统,App Router 是 13+ 引入的新系统。核心区别:App Router 基于 React Server Components,默认在服务端渲染;Pages Router 默认在客户端渲染。新项目用 App Router,老项目不急迁移。
架构对比
| 维度 | Pages Router | App Router |
|---|---|---|
| 目录 | pages/ | app/ |
| 默认渲染 | 客户端 | 服务端(RSC) |
| 数据获取 | getServerSideProps / getStaticProps | async 组件 + fetch |
| 布局 | _app.tsx + 全局 Layout | 嵌套 layout.tsx |
| 路由 | 文件即路由 | 文件夹 + page.tsx |
| API | pages/api/ | app/ + route.ts |
| Loading | 手动管理 | loading.tsx 自动 |
数据获取的变化
Pages Router 用特殊函数获取数据:
tsx// Pages Router export async function getServerSideProps() { const data = await fetchData(); return { props: { data } }; } export default function Page({ data }) { return <div>{data}</div>; }
App Router 直接在组件里 async/await:
tsx// App Router export default async function Page() { const data = await fetchData(); // 服务端直接执行 return <div>{data}</div>; }
App Router 的方式更直观——不需要记特殊函数名,数据获取就是普通的函数调用。
布局系统
Pages Router 的布局是全局的(_app.tsx),切换页面时整个布局重新渲染。
App Router 支持嵌套布局——每个目录可以有 layout.tsx,子路由切换时父布局不重新渲染:
shellapp/ ├── layout.tsx # 根布局(导航栏、页脚)— 永远不重新渲染 ├── dashboard/ │ ├── layout.tsx # 仪表盘布局(侧边栏)— 路由切换不重新渲染 │ ├── page.tsx # /dashboard │ └── settings/ │ └── page.tsx # /dashboard/settings
用户从 /dashboard 切换到 /dashboard/settings 时,根布局和仪表盘布局都保持不变,只有 settings 的 page.tsx 重新渲染。这在 Pages Router 里做不到。
何时迁移
不急迁移的情况:
- 项目稳定运行,没有性能问题
- 团队不熟悉 RSC,迁移风险高
- 大量自定义
_document.tsx/_app.tsx逻辑
应该迁移的情况:
- 需要更好的首屏性能(RSC 显著减少 JS 体积)
- 嵌套布局能解决当前的布局闪烁问题
- 项目刚开始或处于早期
迁移可以渐进式——两个路由可以共存。先把新页面用 App Router 写,老页面逐步迁移。
两者可以共存
shellpages/ ├── index.tsx # Pages Router 处理 ├── about.tsx # Pages Router 处理 app/ ├── dashboard/ │ └── page.tsx # App Router 处理
Next.js 13+ 同时支持两套路由,同一个项目里渐进迁移。但要注意:同一路径不能两边都定义(pages/dashboard.tsx 和 app/dashboard/page.tsx 会冲突)。