Next.js 是基于 React 的全栈框架,它解决了纯 React 应用在服务端渲染(SSR)、静态生成(SSG)、文件系统路由、API 构建等方面的工程化问题。自 2016 年发布以来,Next.js 已成为 React 生态中最主流的全栈解决方案,Vercel 公司持续维护并提供部署支持。
24.2.1 Pages Router 与 App Router 的演进
Next.js 13 引入了全新的 App Router,与传统的 Pages Router 并存。理解两者差异是掌握 Next.js 的关键起点。
| 对比维度 | Pages Router (/pages) | App Router (/app) |
|----------|--------------------------|----------------------|
| 路由定义方式 | 文件即路由,页面组件默认导出 | 文件夹 + page.js 约定 |
| 布局系统 | 需要通过 _app.js / _document.js 或手动嵌套 | 内置 layout.js,支持嵌套布局和持久化 |
| 数据获取 | getServerSideProps、getStaticProps、getInitialProps | async 组件直接获取数据,支持 Server Components |
| 渲染模式 | SSG / SSR / ISR 通过导出函数区分 | 静态默认,动态显式声明(cookies() 等) |
| 服务端组件 | 不支持 | 原生支持 React Server Components |
| 流式渲染 | 通过 Suspense 部分支持 | 原生 loading.js、Streaming 优先 |
| 适用场景 | 成熟稳定,老项目维护 | 新项目推荐,功能更现代 |
App Router 的核心优势:将所有组件默认视为服务器组件(RSC),只有显式添加 'use client' 指令的组件才会在客户端渲染。这带来了更小的客户端 JS 体积和天然的服务端能力(直接访问数据库、文件系统等)。同时,基于文件夹的嵌套路由和布局系统使得复杂应用的结构更直观。
24.2.2 文件系统路由:约定大于配置
Next.js 的路由系统通过文件目录结构自动生成,无需手动配置路由表。
Pages Router 示例:
pages/
index.js → /
about.js → /about
blog/
[slug].js → /blog/:slug
index.js → /blog
App Router 示例:
app/
page.js → /
about/
page.js → /about
blog/
[slug]/
page.js → /blog/:slug
page.js → /blog
layout.js → 根布局(包裹所有页面)
在 App Router 中,每个目录下可以有以下特殊文件:
page.js— 定义页面 UI,必选。layout.js— 定义共享布局,子页面会被渲染到<children>插槽中,导航时布局保持不卸载。loading.js— 页面加载时显示的 Suspense 后备 UI,自动包裹外层。error.js— 错误边界组件,捕获页面错误并显示降级 UI。not-found.js— 404 页面。route.js— 纯 API 路由(替代 Pages Router 的/pages/api)。
这种约定式路由极大简化了路由配置,并天然支持代码分割和预加载。
24.2.3 数据获取:从方法导出到直接异步
Pages Router 的数据获取是通过在组件文件中导出具名函数实现的:
// pages/products.js
export async function getStaticProps() {
const res = await fetch('https://api.example.com/products');
const products = await res.json();
return { props: { products }, revalidate: 3600 }; // ISR
}
export async function getServerSideProps(context) {
const { params } = context;
const res = await fetch(`https://api.example.com/products/${params.id}`);
const product = await res.json();
return { props: { product } };
}
这两种做法分别对应 SSG 和 SSR,但它们是分离的函数,组件本身是普通 React 组件,无法直接在组件代码里获取数据。
App Router 的数据获取得益于 Server Components,组件本身可以是异步函数,在服务端直接执行:
// app/products/page.js
export default async function ProductsPage() {
const products = await fetch('https://api.example.com/products', {
next: { revalidate: 3600 } // 静态 + ISR
});
const data = await products.json();
return (
<ul>
{data.map(p => <li key={p.id}>{p.name}</li>)}
</ul>
);
}
对于需要动态参数的页面:
// app/products/[id]/page.js
export default async function ProductPage({ params }) {
const product = await fetch(`https://api.example.com/products/${params.id}`);
const data = await product.json();
return <div>{data.name}</div>;
}
这种模式将数据获取和 UI 渲染放在同一位置(共置),去掉了额外的导出函数,让代码更内聚。同时 fetch 请求会自动被 Next.js 缓存和去重。
24.2.4 渲染策略:SSG、SSR、ISR、动态渲染
Next.js 支持多层渲染策略,在 App Router 中更加灵活:
- 静态生成(SSG):默认行为。构建时生成 HTML,适合内容不经常变化的页面(博客、文档)。任何不依赖动态数据的页面都会在构建时被预渲染。
- 增量静态再生成(ISR):通过
fetch的next.revalidate选项设置重建间隔,在后台重新生成页面,实现准动态更新。 - 服务端渲染(SSR):当页面使用了动态函数(如
cookies()、headers()、searchParams),Next.js 会自动在请求时渲染,返回最新数据。 - 动态渲染:任何未显式设置
revalidate的页面都会根据具体情况在运行时决定,Next.js 14+ 更推荐这种按需的渲染方式。
在出现 App Router 之前,开发者需要显式决定使用 getStaticProps 还是 getServerSideProps;而 App Router 中,路由的渲染方式由代码中是否使用动态数据源自动判断,这使得选择更加自然。
24.2.5 布局与嵌套布局
App Router 的布局系统堪称革命性改进。布局组件是持久的,路由切换时不会重新挂载,这为 Sidebar、Header 等全局元素提供了极佳的性能表现。
// app/dashboard/layout.js
export default function DashboardLayout({ children }) {
return (
<div className="dashboard">
<aside><Sidebar /></aside>
<main>{children}</main>
</div>
);
}
任何在 /dashboard 下的页面都会渲染在该布局的 children 插槽中。嵌套层级可以任意深,子布局会自动包裹。
24.2.6 API 路由与中间件
Next.js 提供了全栈能力,无需额外搭建后端服务即可编写 API。
Pages Router 的 API 路由:
// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ name: 'John' });
}
App Router 的 Route Handlers:
// app/api/hello/route.js
export async function GET(request) {
return Response.json({ name: 'John' });
}
此外,middleware.js 允许在请求到达页面或 API 之前执行逻辑(如权限校验、重定向):
// middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
if (!request.cookies.has('token')) {
return NextResponse.redirect(new URL('/login', request.url));
}
}
24.2.7 部署与优化
Next.js 官方推荐部署在 Vercel,提供了自动化的 ISR 缓存、边缘函数、分析等服务。但也可以部署在任何 Node.js 环境或通过 Docker 自托管。构建输出 (next build) 会生成一个混合应用,每个页面可以独立选择渲染模式。
核心优化点:
- 图片优化:内置
next/image组件自动懒加载、格式转换。 - 字体优化:
next/font在内联字体时优化 CLS。 - 代码分割:按路由自动分割,
lazy.js支持动态导入。 - 预取:
<Link>组件在视口可见时自动预取目标页面资源。
小结
Next.js 核心体系以文件系统路由为骨架,以 App Router / Pages Router 为双轨,在数据获取、渲染策略、布局嵌套等方面提供了高度集成且实用的解决方案。对于现代 React 开发者,掌握 Next.js 是构建生产级 SSR/全栈应用不可或缺的技能。