Next 和 Rsc

社区来稿 · Liu由用户发布,不代表 batype 本人观点

·712 字 · 约 2 分钟

React Server Components(RSC)和 Next.js


RSC(React Server Components)与 Next.js 常见问题整理#

1. RSC(React Server Components)是什么?#

  • 只在服务端渲染的组件,不会被打包到客户端 JS。
  • 可以直接访问数据库、API、文件等服务端资源。
  • 目标:提升首屏性能、减小客户端 JS 体积、提升数据安全性。

2. RSC 的优缺点#

优点:

  • 极致性能优化(减少客户端 JS 体积)
  • 服务端可直接访问敏感资源
  • 灵活组合 SSR/SPA/静态等渲染模式
  • 数据获取逻辑可直接写在组件里

缺点/挑战:

  • 生态尚未完全成熟
  • 需要区分 Server/Client 组件,心智负担增加
  • 调试和部署复杂度提升
  • Server 组件不能用 useState/useEffect 等客户端 Hook

3. RSC 现在实际有应用吗?#

  • Next.js 13/14 的 app router 已经原生支持 RSC,Vercel、Meta 等公司已在生产环境试点。
  • 目前主流用法是 Next.js app 目录下的页面和组件。

4. 什么时候用 Server Component,什么时候用 Client Component?#

Server Component 适合:

  • 只展示内容、无交互、无副作用的组件
  • 需要服务端数据、SEO、数据库访问的组件

Client Component 适合:

  • 需要响应用户交互(如点击、输入、动画等)
  • 需要用 useState/useEffect/useRef/useReducer 等 Hook
  • 需要访问浏览器 API 的组件

判断口诀:

  • “能用 Server 就用 Server,需要交互再用 Client”
  • “展示用 Server,交互用 Client”

5. Server Component 能用 useSWR/react-query 这类库吗?#

  • 不能。Server Component 不能用 useSWR、react-query 等客户端数据请求库,也不能用 useEffect/useState。
  • Server Component 推荐直接用 async/await、fetch、数据库查询等服务端数据获取方式。
  • useSWR/react-query 只能在 Client Component 里用,适合需要前端动态请求、轮询、懒加载等场景。

6. Next.js 如何处理大量页面(如一千个文章详情)的渲染和打包?#

  • Next.js 支持 SSG(静态生成)、SSR(服务端渲染)、ISR(增量静态生成)三种模式。
  • 不会把所有页面都打包成静态资源,除非你在 generateStaticParams 里全部返回。
  • 推荐用 ISR 或 SSR,按需生成和缓存页面,兼顾性能和实时性。
  • app router 默认就是“智能按需渲染”,不会导致包体积暴涨。

7. 三种模式的代码实现(TypeScript 示例)#

SSG(静态生成)#

export async function generateStaticParams() {
  const ids = await fetchAllPostIds();
  return ids.map(id => ({ id }));
}

export default async function Page({ params }: { params: { id: string } }) {
  const res = await fetch(`https://api.example.com/posts/${params.id}`);
  const post = await res.json();
  return <div>{post.title}</div>;
}

SSR(服务端渲染)#

export default async function Page({ params }: { params: { id: string } }) {
  const res = await fetch(`https://api.example.com/posts/${params.id}`, {
    cache: "no-store", // 强制 SSR
  });
  const post = await res.json();
  return <div>{post.title}</div>;
}

ISR(增量静态生成)#

export async function generateStaticParams() {
  const hotIds = await fetchHotPostIds();
  return hotIds.map(id => ({ id }));
}

export default async function Page({ params }: { params: { id: string } }) {
  const res = await fetch(`https://api.example.com/posts/${params.id}`, {
    next: { revalidate: 60 }, // 60秒自动后台更新
  });
  const post = await res.json();
  return <div>{post.title}</div>;
}

8. revalidate: 60 的含义#

  • 表示页面缓存 60 秒,后台自动更新一次。
  • 不是每 60 秒主动刷新所有页面,而是“有访问才后台再生”。
  • 绝大多数情况下,服务器压力远小于 SSR,且比纯 SSG 灵活。
  • 可根据业务需求灵活调整 revalidate 的时间。

如需更详细的原理、代码或有其他问题,欢迎随时补充!