两种路由器的前世今生
Next.js 的路由系统经历了一次根本性的重构。Pages Router 陪伴开发者走过了六年,建立了稳固的心智模型;App Router 则是 Vercel 团队对 React 未来方向的押注,代表着一种全新的开发范式。
理解两者的差异,不仅是技术选型的需要,更是理解现代前端演进方向的窗口。
架构层面的根本差异
渲染模型
Pages Router 的渲染模型相对简单:
- 每个页面是一个独立的入口点
- 数据获取通过
getServerSideProps/getStaticProps在页面级别完成 - 客户端和服务端的边界清晰:服务端准备数据,客户端渲染 UI
App Router 引入了组件级别的服务端渲染:
- 默认所有组件在服务端渲染
- 需要客户端交互的组件用
'use client'标记 - 数据获取可以发生在任意组件层级
这看起来只是灵活性的提升,但实际上改变了整个应用的思考方式。
布局系统
Pages Router 的布局是"自己搞定"的:
- 通过
_app.js定义全局布局 - 页面级布局需要手动组合高阶组件
- 导航时布局会重新渲染
App Router 内置了嵌套布局:
layout.js文件自动创建布局层级- 导航时布局状态保持,只重新渲染变化的部分
- 天然支持并行路由和拦截路由
对于复杂的多层级导航,App Router 的布局系统省去了大量样板代码。
数据获取
这是两种架构差异最明显的地方:
| 特性 | Pages Router | App Router |
|---|---|---|
| 数据获取位置 | 页面顶层 | 任意组件 |
| 获取方式 | 专用函数 | async 组件 / fetch |
| 缓存控制 | 手动管理 | 框架内置 |
| 流式渲染 | 不支持 | 原生支持 |
| 并行数据获取 | 需手动处理 | 自动并行 |
App Router 中,一个组件直接 await fetch(...) 就能获取数据,无需在页面顶层统一处理再层层传递。这种"就近获取"的模式让组件更加自包含。
性能特点对比
首屏加载
Pages Router:
- 所有页面级代码打包在一起
- 数据获取阻塞页面渲染
- 典型的"白屏 → 完整页面"体验
App Router:
- Server Components 不增加客户端 bundle
- 支持流式渲染,可以渐进展示
- Suspense 边界内的内容独立加载
实测数据显示,相同功能的页面,App Router 版本的 JavaScript bundle 大小通常减少 20-40%。但这个优势需要正确使用 Server Components 才能体现。
导航性能
Pages Router 的导航:
- 触发路由变化
- 下载目标页面代码(如果没缓存)
- 执行数据获取(
getServerSideProps) - 渲染新页面
App Router 的导航:
- 触发路由变化
- 复用不变的布局
- 流式加载变化的部分
- 渐进渲染
关键差异在于布局复用。一个典型的后台应用,侧边栏和顶部导航在页面切换时保持不变,只有内容区更新。App Router 天然支持这种模式,Pages Router 需要额外处理。
缓存与重验证
Pages Router 的缓存完全自理,你可以用 SWR、React Query 等库来管理。
App Router 内置了多层缓存:
- Request Memoization:同一渲染周期内相同请求自动去重
- Data Cache:fetch 结果持久化缓存
- Full Route Cache:静态路由的完整 HTML 缓存
- Router Cache:客户端导航的路由缓存
这套缓存系统很强大,但也带来了学习曲线。Next.js 15 已经简化了默认行为,但理解各层缓存的工作方式仍然必要。
开发体验差异
心智模型
Pages Router 的心智模型接近传统 MVC:
- 路由文件 = 控制器
- 数据获取 = 查询数据
- 返回 JSX = 渲染视图
这个模型直观,容易上手,后端开发者也能快速理解。
App Router 的心智模型更接近组件化:
- 每个组件是独立的渲染单元
- 数据和 UI 就近结合
- 服务端/客户端边界需要主动划分
这种模型更灵活,但也更抽象,需要一定的适应期。
调试体验
Pages Router 的调试相对简单:
- 清晰的服务端/客户端分界
- 错误信息直接定位到数据获取函数
- 传统的 console.log 工作良好
App Router 的调试更复杂:
- Server Components 的 console.log 在终端输出
- 客户端组件的 log 在浏览器控制台
- 水合错误的排查需要理解 RSC 协议
不过 Next.js 15 已经大幅改进了错误提示,调试体验比早期版本好很多。
生态兼容性
Pages Router 几乎兼容所有 React 生态:
- 任何客户端状态管理库
- 任何 CSS-in-JS 方案
- 任何表单库
App Router 有一些限制:
- 某些 CSS-in-JS 库需要适配(运行时生成样式的方案)
- Context 的使用需要注意服务端/客户端边界
- 部分库尚未适配 Server Components
这个差距在逐渐缩小,主流库都在积极适配。但如果你的项目依赖某个小众库,升级前需要验证。
选型决策框架
选择 Pages Router 的情况
团队熟悉度:如果团队对 Pages Router 已经很熟练,且项目时间紧张,继续使用是务实的选择。
简单的页面应用:营销网站、文档站点等页面结构简单的项目,Pages Router 足够胜任,App Router 的优势体现不明显。
深度依赖特定库:如果项目严重依赖某个尚未适配 App Router 的库,强行迁移的成本可能很高。
稳定性优先:App Router 虽然已经稳定,但相比 Pages Router 六年的积累,边缘情况的处理可能还有差距。对于金融、医疗等对稳定性要求极高的场景,Pages Router 是更保守的选择。
选择 App Router 的情况
复杂的嵌套布局:如果应用有多层嵌套布局、多个独立的内容区域,App Router 的布局系统能省很多代码。
性能敏感:需要精细控制哪些代码在服务端运行、哪些在客户端运行,追求最小的 JavaScript bundle。
流式渲染需求:希望页面渐进加载,提升用户感知速度。
长期投资:新项目打算维护多年,希望跟上 React 和 Next.js 的演进方向。
决策清单
回答以下问题,帮助做出选择:
- 项目是新建还是现有项目改造?
- 团队对 Server Components 的理解程度?
- 有没有严重依赖的第三方库?
- 应用的布局复杂度如何?
- 对首屏性能的要求有多高?
- 项目的预期生命周期是多长?
如果多数答案指向"新项目、愿意学习、无特殊依赖、布局复杂、性能敏感、长期维护",App Router 是更好的选择;反之则 Pages Router 更稳妥。
迁移策略
如果决定从 Pages Router 迁移到 App Router,以下是经过验证的策略。
渐进式迁移
Next.js 支持两种路由器并存,这是官方推荐的迁移方式:
- 保持
pages目录:现有页面继续工作 - 新增
app目录:新功能用 App Router 开发 - 逐页迁移:优先迁移独立的、不涉及复杂状态的页面
- 最后处理共享逻辑:布局、中间件、状态管理
关键原则:不要一次性重写。迁移是高风险操作,渐进式才是稳妥之道。
迁移清单
路由文件映射:
pages/index.js→app/page.jspages/about.js→app/about/page.jspages/blog/[slug].js→app/blog/[slug]/page.js
数据获取改造:
getServerSideProps→ async 组件 + fetchgetStaticProps→ async 组件 + fetch + 缓存配置getStaticPaths→generateStaticParams
API 路由:
pages/api/*.js→app/api/*/route.js- 函数签名从
(req, res)改为(request)
布局提取:
_app.js中的全局布局 →app/layout.js- 页面级布局 → 对应目录的
layout.js
常见迁移陷阱
CSS-in-JS 问题:Emotion、styled-components 等库需要特殊配置才能在 App Router 中工作。提前查阅官方文档。
状态提升问题:Server Components 不能使用 hooks,原来的状态逻辑可能需要重构,把状态下沉到 Client Components。
第三方脚本:原来在 _document.js 中添加的第三方脚本,需要迁移到 app/layout.js 或使用 next/script。
404 和错误页面:pages/404.js 变成 app/not-found.js,pages/_error.js 变成 app/error.js。
面向未来的思考
React 团队明确表示,Server Components 是 React 的未来方向。Next.js 的 App Router 是目前 Server Components 最成熟的生产级实现。
从这个角度看,学习 App Router 不仅是学习一个路由系统,而是学习 React 的下一个十年。
但技术选型不是追热点,而是解决实际问题。如果 Pages Router 能很好地满足需求,没必要为了"新"而迁移。等团队有精力、有需求的时候再动,比仓促迁移踩一堆坑要明智得多。
总结
| 维度 | Pages Router | App Router |
|---|---|---|
| 学习曲线 | 平缓 | 陡峭 |
| 心智模型 | MVC 风格 | 组件化 |
| 布局能力 | 基础 | 强大 |
| 数据获取 | 页面级 | 组件级 |
| 性能上限 | 中等 | 高 |
| 生态兼容 | 完善 | 逐步完善 |
| 未来趋势 | 维护模式 | 主推方向 |
最终建议:新项目优先考虑 App Router,现有项目视情况渐进迁移。无论选择哪个,都要深入理解其设计理念,而不只是照着文档抄代码。
相关文章推荐:


