Next.js 13变化有多大?

Next.js 13+ 推出的 App Router 是一次重大架构升级,彻底改变了数据获取的方式。

它最大的特点是拥抱了 Web 标准 ,不再需要 getStaticPropsgetServerSideProps 这两个专属函数,而是直接使用 React 核心特性 (如 async/await 组件、use 钩子)来实现数据获取。使用NEXT 写起来越来越"像"React

一、核心变化:从"生命周期"到"组件形态"

在 App Router 中,页面(Page)和布局(Layout)本身就是 Async 组件 ,可以直接在组件顶层 await 获取数据,逻辑更直观。

特性 Pages Router (旧) App Router (新)
数据获取方式 专属 API:getStaticProps / getServerSideProps 直接 async/await (组件内)
运行环境 函数运行时 组件所在的渲染边界 (服务端/客户端)
代码位置 必须导出单独的函数 与组件代码写在一起
核心思维 基于路由的"文件系统" + 数据函数 基于组件树的 React 服务器组件

二、App Router 里怎么替代?

1. 替代 getStaticProps (静态生成)

在旧方案中,我们用它来在构建时生成静态页面。
新方案:直接在组件顶层 await,并开启缓存。

jsx 复制代码
// app/posts/page.js (App Router 页面)
import PostList from './PostList'

// 这是一个 Server Component (默认就是),可以直接 async
export default async function PostsPage() {
  // 直接在组件里请求数据
  // 默认情况下,fetch 会被自动缓存 (等同于 getStaticProps)
  const res = await fetch('https://api.example.com/posts')
  const posts = await res.json()

  return <PostList posts={posts} />
}
2. 替代 getServerSideProps (服务端渲染)

在旧方案中,我们用它来每次请求都获取最新数据。
新方案:使用 fetch 并配置 cache: 'no-store'

jsx 复制代码
// app/dashboard/page.js
export default async function DashboardPage() {
  // 添加 no-store,每次访问都会重新请求 (等同于 getServerSideProps)
  const res = await fetch('https://api.example.com/user-data', {
    cache: 'no-store'
  })
  const userData = await res.json()

  return <DashboardContent data={userData} />
}
3. 替代 revalidate (增量静态再生 ISR)

旧方案用 revalidate: 10 来定时更新,新方案更灵活。

jsx 复制代码
// app/blog/page.js
export default async function BlogPage() {
  // 后台每 60 秒重新验证并更新数据
  const res = await fetch('https://api.example.com/blog-posts', {
    next: { revalidate: 60 }
  })
  const posts = await res.json()

  return <BlogList posts={posts} />
}

三、客户端组件怎么获取数据?

如果是需要在浏览器运行、或依赖用户交互的客户端组件(带 'use client'),不能直接 await,需使用 React 的 use 钩子

jsx 复制代码
'use client'
import { use } from 'react'

export default function ClientPost({ promise }) {
  // use 可以直接 resolve 一个 Promise
  const post = use(promise)
  
  return <div>{post.title}</div>
}

// 在父页面调用
import ClientPost from './ClientPost'
export default function Page() {
  // 父组件是 Server Component,可以直接 async
  const fetchPost = async () => {
    const res = await fetch('...')
    return res.json()
  }

  // 把 Promise 传给客户端组件
  return <ClientPost promise={fetchPost()} />
}

三、SSG动态路由有什么变化?

在 Next.js 13+ App Router 里,getStaticPaths 被一个新函数替代了:

✨ 新名字:generateStaticParams

它的作用完全等同于旧的 getStaticPaths ,专门用来处理动态路由 (比如 /posts/[id]/product/[slug]),告诉 Next.js:
构建时要提前生成哪些页面?

旧版 Pages Router:getStaticPaths
js 复制代码
// pages/posts/[id].js
export async function getStaticPaths() {
  return {
    paths: [
      { params: { id: '1' } },
      { params: { id: '2' } },
    ],
    fallback: 'blocking' // 重要
  };
}
新版 App Router:generateStaticParams
js 复制代码
// app/posts/[id]/page.js
// 直接导出这个函数就行
export async function generateStaticParams() {
  // 这里返回要预先生成的所有 id
  return [
    { id: '1' },
    { id: '2' },
  ];
}
区别:
  • 不用写 pathsparams
  • 不用写 fallback
  • 默认就是 fallback: blocking(最常用、最安全的模式)

完整可复制示例

这是 App Router 动态路由 + 静态生成的标准写法

jsx 复制代码
// app/posts/[id]/page.js

// 1. 告诉 Next.js 构建时生成哪些页面
export async function generateStaticParams() {
  // 你可以在这里请求接口获取所有文章ID
  // const res = await fetch('https://api.example.com/posts')
  // const posts = await res.json()

  // 返回要预先生成的参数列表
  return [
    { id: '1' },
    { id: '2' },
    { id: '3' },
  ];
}

// 2. 页面组件(默认 async 服务端组件)
export default async function PostPage({ params }) {
  const { id } = params;

  // 自动缓存 = 相当于 getStaticProps
  const res = await fetch(`https://api.example.com/posts/${id}`);
  const post = await res.json();

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  );
}

旧版 Pages Router 新版 App Router 作用
getStaticProps 直接 async await fetch 构建时获取数据
getStaticPaths generateStaticParams 动态路由预生成页面
revalidate fetch(..., { next: { revalidate: 60 } }) 定时刷新

总结

App Router 的核心思想是 "服务器组件"

  1. 默认就是服务端,能直接读写文件、调接口、连数据库,无需特殊 API。
  2. fetch 自带缓存 ,通过 cachenext.revalidate 配置,完美覆盖了 SSG、SSR、ISR 所有场景。
  3. 代码更集中,逻辑更清晰,完全符合 React 的未来发展方向。
相关推荐
代码搬运媛7 小时前
Jest 测试框架详解与实现指南
前端
counterxing8 小时前
我把 Codex 里的 Skills 做成了一个 MCP,还支持分享
前端·agent·ai编程
wangqiaowq8 小时前
windows下nginx的安装
linux·服务器·前端
之歆9 小时前
DAY_12JavaScript DOM 完全指南(二):实战与性能篇
开发语言·前端·javascript·ecmascript
发现一只大呆瓜9 小时前
Vite凭什么这么快?3分钟带你彻底搞懂 Vite 热更新的幕后黑手
前端·面试·vite
Maimai108089 小时前
React如何用 @microsoft/fetch-event-source 落地 SSE:比原生 EventSource 更灵活的实时推送方案
前端·javascript·react.js·microsoft·前端框架·reactjs·webassembly
kyriewen11 小时前
产品经理把PRD写成“天书”,我用AI半小时重写了一遍,他当场愣住
前端·ai编程·cursor
humcomm11 小时前
元框架的工作原理详解
前端·前端框架
canonical_entropy11 小时前
Attractor Before Harness: AI 大规模开发的方法论
前端·aigc·ai编程
zhangxingchao12 小时前
多 Agent 架构到底怎么选?从 Claude Agent Teams、Cognition/Devin 到工程落地原则
前端·人工智能·后端