Next客户端渲染BSR、服务器端渲染SSR、静态站点生成SSG

半兽人 发表于: 2025-03-11   最后更新时间: 2025-03-11 11:12:32  
0 订阅, 132 游览

在 Next.js 中,BSR(Browser-Side Rendering)、SSR(Server-Side Rendering)和 SSG(Static Site Generation) 是三种常见的渲染方式,它们各有适用场景:


1. BSR(Browser-Side Rendering,浏览器端渲染)

BSR 指的是在浏览器端动态获取数据并渲染页面。在 Next.js 中,这通常发生在 useEffect() 或客户端 API 请求中。

特点

  • HTML 仅包含基本结构,数据由 JavaScript 在客户端请求后填充。
  • SEO 不友好,因为搜索引擎可能抓取不到完整内容。
  • 适用于用户特定数据(如个性化内容)或数据变化频繁的页面。

示例

import { useEffect, useState } from 'react';

export default function Page() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('/api/data')
      .then(res => res.json())
      .then(data => setData(data));
  }, []);

  return <div>{data ? data.message : '加载中...'}</div>;
}

2. SSR(Server-Side Rendering,服务器端渲染)

SSR 指的是 在服务器端渲染 HTML 并返回给客户端。Next.js 使用 getServerSideProps() 来实现 SSR。

特点

  • SEO 友好,因为 HTML 是完整的,可以被搜索引擎抓取。
  • 页面在每次请求时都在服务器端获取最新数据。
  • 性能比 BSR 好,但每次请求都会占用服务器资源,可能会增加负载。

示例

export async function getServerSideProps() {
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();

  return { props: { data } };
}

export default function Page({ data }) {
  return <div>{data.message}</div>;
}

3. SSG(Static Site Generation,静态站点生成)

SSG 是 在构建时生成静态 HTML 文件,并在请求时直接返回该文件。Next.js 使用 getStaticProps() 进行 SSG。

特点

  • SEO 友好,HTML 是构建时生成的,搜索引擎可以直接抓取。
  • 性能最佳,因为 HTML 被预先生成,无需服务器计算。
  • 适用于静态内容(如博客、文档等)。
  • 适合不频繁变化的数据,但可结合 ISR(Incremental Static Regeneration)动态更新

示例

export async function getStaticProps() {
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();

  return { props: { data }, revalidate: 10 }; // 10 秒后自动重新生成
}

export default function Page({ data }) {
  return <div>{data.message}</div>;
}

总结

渲染方式 适用场景 SEO 友好性 性能 数据获取时间
BSR(客户端渲染) 交互性强、个性化内容 ❌ 差 ⬆ 快(但可能影响 FCP) 客户端请求后
SSR(服务器端渲染) 需要最新数据、SEO 重要 ✅ 好 ⬇ 慢(依赖服务器) 每次请求时
SSG(静态生成) 静态内容、博客等 ✅ 最佳 ⬆⬆ 最高 构建时(可用 ISR 更新)

如果页面的数据不会频繁更新,建议使用 SSG(静态生成)提高性能;如果需要每次请求最新数据,使用 SSR(服务器渲染);如果是个性化内容或用户特定数据,使用 BSR(客户端渲染)。

怎么判断我现在的程序使用的是什么呢?

要判断你的 Next.js 页面正在使用 BSR、SSR 还是 SSG,你可以使用以下方法:


1. 通过开发代码检查

在 Next.js 中,不同的渲染模式使用不同的方法:

渲染模式 关键方法
BSR(客户端渲染) 只使用 useEffect() 或 API 请求,无 getStaticProps() / getServerSideProps()
SSR(服务器端渲染) 使用 getServerSideProps()
SSG(静态站点生成) 使用 getStaticProps()

你可以打开 pages/ 目录下的文件,检查是否有 getStaticProps()getServerSideProps() 方法:

// 如果有 getStaticProps(),说明是 SSG
export async function getStaticProps() {}

// 如果有 getServerSideProps(),说明是 SSR
export async function getServerSideProps() {}

// 只有 useEffect() 而没有上面两个方法,说明是 BSR(客户端渲染)

2. 通过 Next.js 开发环境的 console.log() 检查

getServerSideProps()getStaticProps() 里加 console.log(),然后在服务器终端(不是浏览器控制台)查看是否打印:

export async function getServerSideProps() {
  console.log('SSR 渲染发生了!');
  return { props: { time: new Date().toISOString() } };
}
  • 如果你在浏览器刷新后,终端(服务器端)有日志,说明使用的是 SSR
  • 如果终端没有日志,而只在构建时打印,说明是 SSG
  • 如果 console.log() 代码在 useEffect() 里运行,说明是 BSR

3. 通过浏览器检查 页面请求方式

方法 1:查看网络请求

  • 打开 浏览器开发者工具(F12 / Ctrl + Shift + I)。
  • 进入 Network(网络) 选项卡。
  • 刷新页面,找到 document 类型的请求(通常是 localhost:3000 或你的页面 URL)。
  • 查看 响应头(Response Headers)。

判断方式

  1. SSR

    • 响应头会包含 x-nextjs-page,并且 cache-control 可能是 no-cache(意味着服务器每次都重新生成)。
    • 示例
      x-nextjs-page: /my-page
      cache-control: no-store, no-cache, must-revalidate
      
  2. SSG

    • 响应头 cache-control 可能是 public, max-age=...,表示该页面是静态的,可以缓存。
    • 示例
      cache-control: public, max-age=3600, stale-while-revalidate=59
      
  3. BSR

    • 页面加载后,会有额外的 API 请求(通常是 fetch('/api/...'))。
    • 只有 document 请求时,返回的 HTML 可能是一个基本结构,数据是客户端动态填充的。

方法 2:查看 HTML 源码

  • 在页面上 右键 → 查看页面源代码(或者按 Ctrl + U)。
  • 如果数据是完整的,说明是 SSR 或 SSG(服务器已渲染)。
  • 如果数据是空的,JS 负责填充,说明是 BSR(客户端渲染)

示例:

<!-- 服务器渲染 (SSR 或 SSG) -->
<div id="content">Hello, SSR!</div>

<!-- 客户端渲染 (BSR) -->
<div id="content"></div>
<script>
  document.getElementById('content').innerHTML = 'Hello, BSR!';
</script>

4. 通过 next build && next start 观察

如果你在 next dev(开发模式)下不确定,可以运行:

next build && next start

然后:

  • 刷新页面
  • 观察终端日志
  • 结合 console.log() 判断是否有服务器端执行

最终总结

判断方法 BSR(客户端渲染) SSR(服务器端渲染) SSG(静态站点生成)
代码检查 useEffect() 进行数据请求 getServerSideProps() getStaticProps()
终端日志 只在浏览器执行 console.log() 服务器每次请求都会有 console.log() 服务器 构建时 执行 console.log()
网络请求 额外的 fetch() 请求 document 请求有 cache-control: no-cache document 请求有 cache-control: public, max-age=...
查看 HTML 源码 初始内容为空,JS 填充 HTML 直接包含完整数据 HTML 直接包含完整数据
运行 next build && next start 不影响 每次请求都会重新执行 只在构建时执行

如果你不确定,建议:

  1. 查看代码是否有 getServerSideProps() / getStaticProps()
  2. console.log() 观察是否在服务器端运行
  3. 用浏览器开发者工具检查 HTML 和网络请求

这样你就能判断你的 Next.js 应用使用的是什么渲染模式了!

示例

  const handleSaveName = async () => {
    try {
      setEditing(true)
      await updateUserProfile({ url: 'account/name', body: { name: editName } })
      notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
      mutateUserProfile()
      setEditNameModalVisible(false)
      setEditing(false)
    }
    catch (e) {
      notify({ type: 'error', message: (e as Error).message })
      setEditNameModalVisible(false)
      setEditing(false)
    }
  }

这个用的是什么?

你的 handleSaveName 方法是 客户端渲染(BSR,Browser-Side Rendering),它不涉及 getServerSideProps()getStaticProps(),而是通过 前端 JavaScript 进行 API 调用并更新 UI。


判断依据

  1. 没有 getServerSideProps()getStaticProps()

    • 这段代码是 React 组件内部的一个 async 方法,而不是 Next.js 提供的 getServerSideProps()getStaticProps()
  2. 使用了 await updateUserProfile(...)

    • updateUserProfile 发送 API 请求(可能是 fetch()axios),这是典型的 客户端数据获取(Client-side Fetching)。
    • 服务器不会在页面渲染时提前获取数据,而是等用户触发 handleSaveName 后才请求。
  3. mutateUserProfile()

    • 这可能是 SWRreact-query 之类的状态管理库,用于在客户端重新拉取数据,属于 BSR 逻辑。
  4. setEditing(true)setEditNameModalVisible(false)

    • 这些是 React 状态更新useState()),只在浏览器中运行,不涉及服务器端渲染。

最终结论

这个 handleSaveName 方法属于 BSR(客户端渲染),因为:

  • 数据请求发生在 浏览器端,而不是服务器端。
  • 依赖 useState() 和前端 notify() 来管理 UI 状态。
  • 没有 getServerSideProps()getStaticProps(),不会在页面加载时提前渲染数据。

如何让它使用 SSR?

如果你想让数据请求在 服务器端渲染(SSR) 时执行,而不是在客户端触发,你需要:

  1. 把数据获取逻辑放到 getServerSideProps()

    export async function getServerSideProps(context) {
      const res = await fetch('https://your-api.com/account/name')
      const data = await res.json()
    
      return {
        props: { name: data.name },
      }
    }
    
  2. 这样 name 在服务器端就会预先加载,页面渲染时已经有数据了。

但你的 handleSaveName用户交互触发的操作,一般不会用 SSR,因为 SSR 适合 初始加载,而 handleSaveName 适合 用户操作后的更新,所以 BSR 是合理的选择!

更新于 2025-03-11
在线,10小时前登录

查看Next.js更多相关的文章或提一个关于Next.js的问题,也可以与我们一起分享文章