人人都会AI编程

24.2 Next.js 核心体系

更新时间:2026-07-10

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,支持嵌套布局和持久化 |
| 数据获取 | getServerSidePropsgetStaticPropsgetInitialProps | 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):通过 fetchnext.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/全栈应用不可或缺的技能。