乐闻世界logo
搜索文章和话题

Next.js App Router 与 Pages Router 的核心区别及迁移策略是什么?

2月17日 23:33

Next.js 13+ 引入了全新的 App Router,与传统的 Pages Router 相比有显著差异。App Router 基于 React Server Components 构建,提供了更强大的功能和更好的性能。

主要区别

1. 文件结构

Pages Router:

shell
pages/ index.js about.js api/ users.js

App Router:

shell
app/ page.js about/ page.js api/ users/ route.js

2. 布局系统

App Router 的布局系统更强大:

javascript
// app/layout.js import './globals.css'; export default function RootLayout({ children }) { return ( <html lang="zh-CN"> <body> <header>全局头部</header> {children} <footer>全局页脚</footer> </body> </html> ); } // app/about/layout.js export default function AboutLayout({ children }) { return ( <div className="about-layout"> <aside>关于我们侧边栏</aside> <main>{children}</main> </div> ); }

3. 数据获取方式

Pages Router:

javascript
// pages/index.js export async function getServerSideProps() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return { props: { data } }; } export default function Home({ data }) { return <div>{data.title}</div>; }

App Router:

javascript
// app/page.js async function getData() { const res = await fetch('https://api.example.com/data', { next: { revalidate: 3600 } }); return res.json(); } export default async function Page() { const data = await getData(); return <div>{data.title}</div>; }

4. Server Components vs Client Components

App Router 默认使用 Server Components:

javascript
// app/page.js (Server Component - 默认) async function Page() { const data = await fetch('https://api.example.com/data').then(r => r.json()); return <div>{data.title}</div>; } export default Page; // app/components/Interactive.js (Client Component) 'use client'; import { useState } from 'react'; export default function Interactive() { const [count, setCount] = useState(0); return <button onClick={() => setCount(c => c + 1)}>{count}</button>; }

5. 路由参数

Pages Router:

javascript
// pages/posts/[id].js export async function getStaticPaths() { const posts = await getAllPosts(); return { paths: posts.map(post => ({ params: { id: post.id } })), fallback: 'blocking' }; } export async function getStaticProps({ params }) { const post = await getPost(params.id); return { props: { post } }; }

App Router:

javascript
// app/posts/[id]/page.js export async function generateStaticParams() { const posts = await getAllPosts(); return posts.map(post => ({ id: post.id })); } export default async function PostPage({ params }) { const post = await getPost(params.id); return <article>{post.content}</article>; }

6. 加载状态和错误处理

App Router 内置支持:

javascript
// app/posts/loading.js export default function Loading() { return <div>加载中...</div>; } // app/posts/error.js 'use client'; export default function Error({ error, reset }) { return ( <div> <h2>出错了!</h2> <button onClick={() => reset()}>重试</button> </div> ); } // app/posts/not-found.js export default function NotFound() { return <div>文章未找到</div>; }

7. Server Actions

App Router 独有功能:

javascript
// app/actions.js 'use server'; import { revalidatePath } from 'next/cache'; export async function createPost(formData) { const title = formData.get('title'); const content = formData.get('content'); await savePost({ title, content }); revalidatePath('/posts'); } // app/posts/new/page.js import { createPost } from '../actions'; export default function NewPostPage() { return ( <form action={createPost}> <input name="title" /> <textarea name="content" /> <button type="submit">创建文章</button> </form> ); }

迁移策略

渐进式迁移

javascript
// 可以在同一个项目中同时使用两个 Router // pages/ - 旧代码继续使用 Pages Router // app/ - 新功能使用 App Router // 在 App Router 中链接到 Pages Router <Link href="/old-page">旧页面</Link>

关键迁移步骤

  1. 安装 Next.js 13+ 并更新配置
  2. 创建 app/ 目录结构
  3. 迁移布局到 app/layout.js
  4. 将页面逐步迁移到 app/ 目录
  5. 更新数据获取逻辑
  6. 添加 'use client' 指令到交互式组件
  7. 更新 API 路由为 Route Handlers
  8. 测试并优化性能

性能对比

App Router 优势:

  • 更小的客户端包(Server Components 不发送到客户端)
  • 更好的 SEO(默认服务端渲染)
  • 更灵活的缓存策略
  • 内置加载和错误状态
  • 更简洁的代码结构

Pages Router 优势:

  • 更成熟稳定
  • 更丰富的生态系统和文档
  • 更简单的学习曲线
  • 更多的第三方库支持

最佳实践

  1. 新项目: 优先使用 App Router
  2. 现有项目: 渐进式迁移,先迁移简单页面
  3. 组件选择: 默认使用 Server Components,只在需要交互时使用 Client Components
  4. 数据获取: 利用 fetch API 的缓存选项
  5. 状态管理: Server Actions 替代部分 API 路由

App Router 代表了 Next.js 的未来方向,提供了更现代的开发体验和更好的性能表现。

标签:Next.js