大家好,我是大鱼,一名热爱前端的普通开发者。
今天我们来深入探讨Next.js中两个重要的路由系统:Pages Router和App Router。
什么是Next.js路由?
在开始深入比较之前,让我们先简单回顾一下Next.js的路由系统。Next.js使用基于文件系统的路由,这意味着你文件目录的结构决定了你应用程序的路由结构。
多年来,Next.js开发者习惯将页面放置在"pages"目录中,这就是我们所说的Pages Router。
后来,Next.js推出了新的App Router,显著改变了我们创建页面的方式。
Pages Router:经典而成熟的选择
基本结构
在Pages Router中,你的项目结构通常是这样:
markdown
└── pages
├── about.js
├── index.js
└── team.js
每个JavaScript/TypeScript文件对应一个路由,例如pages/about.js对应/about路由。
特点与使用方式
Pages Router采用"客户端优先"的思维模式,通过getServerSideProps等函数"拉取"服务端能力。数据获取主要在页面级别,集中在getStaticProps/getServerSideProps中。
在Pages Router中,你可以使用useRouterHook来实现页面跳转:
jsx
import { useRouter } from 'next/router';
function MyComponent() {
const router = useRouter();
const handleClick = () => {
router.push('/about');
};
return (
<button onClick={handleClick}>
跳转到关于页面
</button>
);
}
与浏览器原生的window.location.href赋值不同,使用useRouter的push方法不会导致整个页面的完全重加载,这对性能更加有利。
App Router:面向未来的新范式
基本结构
App Router引入了全新的目录结构:
css
src/
└── app
├── about
│ └── page.js
├── globals.css
├── layout.js
├── login
│ └── page.js
├── page.js
└── team
└── route.js
创建应用程序的约定如下:
- 应用中的每个页面都有自己的目录,目录名称定义URL路径
- 浏览器中访问路径时渲染的组件是page.js
- 每个页面的目录中可以放置几个具有保留名称的文件,如
loading.js、template.js和layout.js
核心特性
服务器组件与客户端组件
App Router中最重大的变化是:默认情况下,应用程序目录中的任何组件都是服务器组件。这意味着:
- 服务器组件在服务器上呈现,所有代码都保留在服务器上
- 不能使用客户端功能如window对象或React中的典型钩子
- 可以通过在文件顶部声明"use client"来声明客户端组件
布局系统
App Router原生支持布局,通过layout.js文件实现。布局组件可以应用于多个页面,如果子目录没有单独指定布局,则使用顶级布局。
jsx
// layout.js
export default function LoginLayout({ children }) {
return <div className='login-area'>{children}</div>
}
布局会自动应用于其下的所有页面,无需在页面文件中额外指定。
数据获取
App Router引入了组件级数据获取,与Pages Router的页面级数据获取形成鲜明对比。在Server Component中可以直接使用async/await和fetch:
jsx
async function BlogPost({ slug }) {
const post = await fetch(`/api/posts/${slug}`).then(res => res.json());
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
);
}
深度对比:Pages Router vs App Router
功能特性对比
| 特性 | Pages Router | App Router |
|---|---|---|
| 默认组件类型 | 客户端组件 | 服务器组件 |
| 思维模式 | "客户端优先" | "服务器优先" |
| 数据获取 | 页面级别,集中在getStaticProps/getServerSideProps中 | 组件级别,在各个Server Component内部 |
| 布局系统 | 通过_app.js和getLayout模式实现,非原生 | 原生支持,文件系统结构天然支持嵌套 |
| 客户端JS | 整个页面的所有组件代码都会被发送到客户端 | 只有标记为"use client"的组件及其子组件的JS会被发送 |
性能对比
在性能方面,App Router的架构优势是压倒性的。通过默认使用Server Components,它从根本上解决了客户端JavaScript过大的问题。
学习曲线与生态系统
-
Pages Router:生态系统极其成熟,学习曲线较低,对于有React SPA经验的开发者来说非常熟悉
-
App Router:生态系统正在快速发展中,学习曲线较高,需要理解Server/Client组件的区别等新概念
决策指南:如何选择?
选择 App Router,如果:
- ✅ 你正在开始一个全新的项目,没有历史包袱
- ✅ 性能是你的首要考量,你希望从一开始就构建最快、最轻量的应用
- ✅ 你的应用有复杂的、嵌套的布局和数据依赖关系
- ✅ 你的团队乐于学习和拥抱新技术
- ✅ 你正在构建一个数据密集型、内容驱动的应用(如仪表盘、电商网站、CMS前端)
选择 Pages Router,如果:
- 🟡 你正在维护或迭代一个现有的、基于Pages Router的项目
- 🟡 你的项目高度依赖某个尚未完全支持App Router的第三方库
- 🟡 团队成员对RSC不熟悉,且项目交付时间非常紧张
- 🟡 你的应用是一个非常简单、以交互为主的轻量级SPA,服务端渲染的需求很低
混合模式的可能性
Next.js允许你在同一个项目中同时使用app和pages目录。这为渐进式迁移提供了一条平滑的路径。你可以先在现有项目中引入app目录来开发新功能,逐步体验App Router的优势。
实战建议
从Pages Router迁移到App Router
如果你计划从Pages Router迁移到App Router,可以考虑以下步骤:
- 逐步迁移:利用混合模式,逐步将页面从pages目录迁移到app目录
- 组件适配:将使用React钩子或浏览器API的组件标记为客户端组件
- 数据获取:将getStaticProps/getServerSideProps重构为组件级数据获取
- 布局重构:利用App Router的布局系统简化你的布局代码
开发技巧
- 明确组件边界:在App Router中,要清晰界定服务器组件和客户端组件的职责
- 利用流式渲染:App Router支持流式渲染,可以显著提升用户体验
- 合理使用缓存:App Router提供了更精细的缓存控制机制
结语
App Router无疑是Next.js的未来。它通过React Server Components带来的架构革新,在性能、代码组织和开发体验上都提供了巨大的飞跃。对于新项目,除非有特定的生态限制,否则强烈建议从App Router开始。
希望这篇文章能帮助你理解Next.js中两种路由系统的区别,如果你有任何问题,欢迎在评论区留言讨论!
作者:大鱼,前端开发者,专注于大前端圈技术栈。欢迎关注我的微信公众号<大前端历险记>获取更多前端技术干货。