#题引:我认为跟着官方文档学习不会走歪路
服务器组件渲染到客户端发生了什么?
- 请求到达服务器
用户在浏览器中请求一个页面。
Next.js 服务器接收到这个请求,并根据路由找到相应的页面组件。 - 服务器组件的渲染
Next.js 识别出请求的页面包含服务器组件。
服务器组件在服务器端执行,进行以下操作:
- 数据获取:组件内部可以直接调用 API 或数据库获取所需的数据。
- HTML 生成:根据获取的数据,构建 HTML 内容。
- 生成有效负载
服务器组件生成的 HTML 和相关数据一起被称为React 服务器组件有效负载 (RSC Payload)
。
有效负载是是渲染后的 React 服务器组件树的紧凑二进制表示,包括:
- 服务器组件的渲染结果:组件的结构和内容,组件在服务器端获取的数据等
- 客户端组件应该渲染的位置的占位符以及它们的 JavaScript 文件引用
- 从服务器组件传递到客户端组件的任何 props
- 发送响应到客户端
生成的有效负载通过 HTTP 响应发送到客户端。 - 客户端接收和渲染
浏览器接收到服务器发送的 HTML 内容。
浏览器解析 HTML,将其渲染为可视化的页面。此时,用户可以看到页面的内容,而无需等待 JavaScript 的加载和执行。 - 客户端交互
如果页面中包含客户端组件(例如需要交互的部分),Next.js 会在客户端加载相应的 JavaScript。
客户端组件会接管页面的交互逻辑,使得页面变得动态和响应式。
服务器组件不同的渲染策略
服务器渲染有三种子类型:静态、动态和流式传输。
1: 静态渲染(默认)
使用静态渲染时,路由会在构建时渲染,或在数据重新验证后在后台渲染
步骤:
- 构建时生成:在构建时,Next.js 预先生成页面的 HTML。
- 数据获取:在构建时获取数据并生成静态 HTML。
- 发送静态文件:将生成的静态 HTML 文件存储在 CDN 上。
- 客户端请求:用户请求页面时,直接从 CDN 获取静态 HTML。
- 客户端渲染:浏览器解析并渲染页面。
这种实现方式称之为静态生成SSG,静态渲染本身不依赖于 CDN,但结合使用 CDN 可以显著提高性能和用户体验。是否使用 CDN 取决于具体的项目需求和部署策略。
默认使用静态渲染的意思是:在渲染过程中,如果发现动态 API或未缓存的数据请求(这些数据通常是实时生成的,或者是用户特定的、频繁变化的信息),Next.js 将切换到动态渲染整个路由,否则就会默认为静态渲染,它将在 next build 时被预渲染为静态页面。这些动态API包括:
- cookies
- headers
- connection
- draftMode
- searchParams prop
- unstable_noStore
- unstable_after
2: 动态渲染
使用动态渲染时,路由会在请求时为每个用户渲染,它的流程即上面“服务器组件渲染到客户端发生了什么?“标题下所描述的用例步骤。
当路由具有针对用户个性化的数据或只能在请求时获知的信息时,动态渲染很有用,比如 cookies 或 URL 的搜索参数。
3:流式传输
流式传输(Streaming)是一种用于优化数据加载和页面渲染的技术。它允许服务器在生成页面时逐步发送内容,而不是等待整个页面生成完成后一次性返回。这种方式可以提高用户体验,特别是在处理大型数据集或复杂页面时。
你可以使用 loading.js 和带有 React Suspense 的 UI 组件开始流式传输路由段。
- loading.js 文件用于定义加载状态的 UI。当某个路由段正在加载时,loading.js 可以提供一个用户友好的加载指示器或占位符。
- Suspense 组件允许你在等待某些异步操作(如数据加载)完成时,显示一个替代的 UI(例如加载指示器),然后在操作完成后切换到你的组件。
服务端和客户端组合模式
大多数 Next.js 应用采用的是服务端和客户端的组合模式。这种模式结合了服务器端渲染(SSR)和客户端渲染(CSR)的优点。
- 服务器生成完整的 HTML 页面并发送给客户端。这样可以确保用户在首次加载页面时快速看到内容
- 客户端使用 JavaScript 在浏览器中动态加载和渲染数据。通常在用户与页面交互时(如点击按钮、导航等)进行数据请求。
Nextjs默认服务端组件,如果要使用客户端组件,可以在文件顶部、导入语句之前添加 React 的 “use client” 指令。
实现这种模式内部会涉及到一个API:hydrateRoot,(在 React 18 之前的版本,使用的是 ReactDOM.hydrate)它的主要作用是将服务端生成的 HTML 内容与客户端的 React 组件树进行“水合”(hydration),以便实现客户端的交互功能。
水合:将服务端渲染的静态 HTML 内容与客户端的 React 组件进行结合,使得 React 可以接管这些内容,添加交互性。在水合过程中,React 会保留组件的状态,使得用户在加载页面时不会丢失之前的状态。
服务端组件和客户端组件的不同使用场景的快速总结: