← 返回首页

🚀 SSR & RSC 示例

展示 Next.js 服务端渲染 (SSR) 和 React Server Components (RSC) 特性

✨ React Server Components (RSC)

RSC 是 Next.js 13+ 的核心特性,允许组件在服务端渲染,同时保持与客户端组件的灵活混合。

🖥️ 服务端组件 (Server)

  • • 默认类型,无需声明
  • • 可以直接访问数据库
  • • 支持 async/await
  • • 不增加 JS 包大小
  • • 无法使用 Hooks

💻 客户端组件 (Client)

  • • 使用 "use client" 声明
  • • 可以使用 React Hooks
  • • 支持交互和事件
  • • 访问浏览器 API
  • • 增加 JS 包大小

💻 客户端组件 (Client Component)

交互式计数器

0

⏰ 客户端实时时钟

⏳ 等待挂载...

📌 客户端组件特性

  • • 使用 "use client" 指令声明
  • • 可以使用 React Hooks (useState, useEffect 等)
  • • 可以访问浏览器 API (window, document 等)
  • • 支持事件处理和交互功能
  • • 会增加客户端 JavaScript 包大小

🖥️ 服务端信息

服务器时间2026-01-09T15:05:16.774Z
随机数(服务端生成)774
模拟请求计数6,845
Node.js 版本v24.12.0
运行平台linux

📝 热门文章(服务端数据)

Next.js 15 新特性

ID: 1
作者: 张三👁️ 1,234 次浏览

React 19 性能优化

ID: 2
作者: 李四👁️ 2,345 次浏览

TypeScript 最佳实践

ID: 3
作者: 王五👁️ 3,456 次浏览

⚡ 流式渲染 (Streaming SSR)

使用 React Suspense,页面可以边加载边显示,不需要等待所有数据加载完成!

❌ 传统 SSR (阻塞)

1. 等待所有数据
2. 渲染完整 HTML
3. 发送给浏览器

⏱️ 用户需要等待 1.5s+

✅ 流式 SSR (非阻塞)

1. 立即发送页面框架
2. 显示加载骨架屏
3. 数据就绪后流式更新

⚡ 用户立即看到页面!

实现方式:使用 <Suspense> 包裹慢速组件, 提供 fallback 加载状态。Next.js 会自动处理流式传输。

🌊 流式传输原理

传输时间线

0ms

📤 第一块 (Chunk 1)

HTML 头部、CSS、初始页面结构

50ms

📤 第二块 (Chunk 2)

快速组件的 HTML(立即可用的内容)

100ms

🎨 浏览器渲染

用户看到页面框架和骨架屏

500ms

📤 第三块 (Chunk 3)

Suspense 组件的数据就绪,发送真实 HTML

520ms

✨ 自动替换

React 自动用真实内容替换骨架屏

📡 HTTP 响应头

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
X-Powered-By: Next.js

<!-- 数据会分多次传输,而不是一次性 -->

⚛️ React 的流式渲染机制

1. 标记 Suspense 边界:React 遇到 <Suspense> 时, 会在 HTML 中插入特殊注释标记(如 $?)

2. 发送 Fallback:先发送 fallback 内容(骨架屏), 让用户立即看到页面

3. 后台处理:服务器继续等待 async 组件完成数据获取

4. 发送更新:数据就绪后,通过新的 chunk 发送真实内容和替换脚本

5. 客户端 Hydration:React 在客户端执行脚本,用真实内容替换 fallback

📄 实际 HTML 输出(简化版)

<!-- Chunk 1: 立即发送 -->
<!DOCTYPE html>
<html>
<head>
  <script>/* React 运行时 */</script>
</head>
<body>
  <div id="root">
    <header>立即显示的内容</header>
    
    <!-- Suspense 边界标记 -->
    <!--$?-->
    <template id="B:0"></template>
    
    <!-- Fallback 内容(骨架屏) -->
    <div class="loading-skeleton">
      加载中...
    </div>
    <!--/$-->
    
    <footer>页脚</footer>
  </div>

<!-- Chunk 2: 500ms 后数据就绪,发送 -->
<div hidden id="S:0">
  <!-- 真实的组件内容 -->
  <div class="user-data">
    <h3>用户数据</h3>
    <p>张三 - zhangsan@example.com</p>
  </div>
</div>

<script>
  // React 的替换函数
  $RC = function(id, html) {
    // 找到 template 标记
    const template = document.getElementById(id);
    // 用真实内容替换 fallback
    template.parentNode.replaceChild(
      document.getElementById('S:0').firstChild,
      template.nextSibling
    );
  };
  $RC("B:0");
</script>

</body>
</html>

🔑 关键技术点

  • 分块传输:使用 HTTP Chunked Transfer Encoding
  • 渐进式渲染:浏览器收到部分 HTML 就开始渲染
  • 非阻塞:慢速组件不影响其他内容显示
  • 选择性 Hydration:React 只对需要交互的部分进行 hydrate
  • 自动协调:React 自动处理内容替换,无需手动操作 DOM

⚡ 性能对比

❌ 传统 SSR

  • • TTFB: 1500ms
  • • FCP: 1600ms
  • • LCP: 1700ms

✅ 流式 SSR

  • • TTFB: 50ms ⚡
  • • FCP: 150ms ⚡
  • • LCP: 600ms ⚡

* TTFB: Time to First Byte | FCP: First Contentful Paint | LCP: Largest Contentful Paint

💡 RSC 最佳实践

1️⃣ 默认使用服务端组件

尽可能使用服务端组件,只在需要交互时才使用 "use client"。这样可以减少客户端 JavaScript 包大小,提升性能。

2️⃣ 使用 Suspense 实现流式渲染

用 Suspense 包裹慢速组件,避免阻塞整个页面渲染:

// ✅ 好的做法 - 流式渲染
import { Suspense } from 'react';

function Page() {
  return (
    <>
      <FastComponent />  {/* 立即显示 */}
      <Suspense fallback={<Loading />}>
        <SlowComponent /> {/* 异步加载 */}
      </Suspense>
    </>
  );
}

// ❌ 不好的做法 - 阻塞渲染
async function Page() {
  const data = await fetchSlowData(); // 阻塞!
  return <div>{data}</div>;
}

3️⃣ 组件树的边界

将 "use client" 放在组件树的叶子节点,而不是根节点。例如:

// ✅ 好的做法
function Page() {
  return (
    <div>
      <ServerComponent />      {/* Server */}
      <InteractiveButton />    {/* Client */}
    </div>
  );
}

// ❌ 不好的做法
"use client";
function Page() {  // 整个页面都变成 Client
  return <div>...</div>;
}

4️⃣ 数据获取策略

在服务端组件中直接获取数据,避免额外的 API 请求。可以使用 async/await 直接访问数据库或 API。

5️⃣ 混合使用

服务端组件可以嵌入客户端组件,但客户端组件不能直接导入服务端组件。如需传递,请使用 children prop。

✨ SSR 特性

  • ✓页面内容在服务器端生成,首屏加载速度快
  • ✓SEO 友好,搜索引擎可以直接抓取完整内容
  • ✓可以安全地访问服务端 API、数据库等资源
  • ✓每次请求都会重新渲染,数据实时更新
  • ✓减少客户端 JavaScript 执行,提升性能

🔍 技术实现说明

1. 默认 SSR: Next.js App Router 中,所有组件默认在服务端渲染

2. async/await: 服务端组件可以直接使用 async 函数获取数据

3. 动态渲染: 页面每次请求都会重新渲染,刷新页面可看到数据更新

4. 服务端专属: 可以使用 process、fs 等 Node.js API

5. 查看源码: 右键"查看网页源代码"可看到完整的 HTML 内容

🧪 测试 SSR 效果

  • 刷新页面(F5),观察服务器时间和随机数会变化
  • 右键"查看网页源代码",可以看到完整的数据已经在 HTML 中
  • 禁用 JavaScript 后页面仍然可以正常显示(内容已预渲染)
  • 打开 Network 面板,可以看到 HTML 文档包含完整内容

🖥️ 服务端组件 (Server Component)

🕐 服务端渲染时间

2026-01-09T15:05:21.822Z

此时间在服务端生成,刷新页面会更新

1234

总用户数

567

活跃用户

23

今日新增

👥 用户列表(来自服务端数据库)

张三

zhangsan@example.com

管理员

李四

lisi@example.com

用户

王五

wangwu@example.com

用户

📌 服务端组件特性

  • • 默认就是 Server Component(无需声明)
  • • 可以直接访问数据库、文件系统等后端资源
  • • 可以使用 async/await 异步获取数据
  • • 不会增加客户端 JavaScript 包大小
  • • 无法使用 React Hooks 和浏览器 API
  • • 组件代码不会发送到浏览器