Next.js 13变化有多大?

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

它最大的特点是拥抱了 Web 标准 ,不再需要 getStaticProps 和 getServerSideProps 这两个专属函数,而是直接使用 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' },
  ];
}
区别:
  • 不用写 paths、params 了
  • 不用写 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 自带缓存 ,通过 cache 和 next.revalidate 配置,完美覆盖了 SSG、SSR、ISR 所有场景。
  3. 代码更集中,逻辑更清晰,完全符合 React 的未来发展方向。
相关推荐
福兮说6 小时前
前端下载大文件,点了按钮半天没反应:fetch + blob 的三个问题和三种替代写法
前端·javascript·性能优化·文件下载
GreenTea6 小时前
我把 Agent 的 while 循环拆掉了:一种你可能没想到的 Agent 架构
前端·后端·架构
科技观察哨6 小时前
六足平台选型与纳米定位系统集成:HEB-640六自由度位移台在半导体光刻对准中的参数边界与国产替代评估
前端·人工智能
niucloud-admin7 小时前
JAVA V6 多商户商城 开发文档——web前端
前端
颜进强7 小时前
16 · NestJS LifecycleEvents 生命周期事件:五个钩子、三条边界,和 rag-server 的优雅停机
前端·后端·ai编程
今年下半年8 小时前
【VUE】整合腾讯地图、自定义区域边界、村委名称及资产统计(放大显示资产点位)
前端·javascript·vue.js
郑州光合科技余经理9 小时前
同城电商系统:库存变更怎么同步到订单
java·开发语言·前端·后端·uni-app·php·ai编程
前端snow10 小时前
ai agent --- DeepAgents 中间件
前端
data analyse 45611 小时前
报表能自定义的国内统计工具有哪些
前端·数据分析