服务端组件(Server Components)
next服务端渲染有三种不同的服务器渲染策略:
- 静态渲染(默认):构建路由、数据重新验证时渲染静态页面,并缓存。使用场景:不需要针对用户做个性化处理的页面,如:资讯列表、博文等。
- 动态渲染:路由请求时在服务端进行针对该路由静态页面的渲染,服务端渲染。使用场景:需要针对不同客户进行个性化处理的页面,如:页面携带用户信息、权限菜单等。
- 数据流传输:路由下的工作页面被分割成多个模块,以流式传输到用户客户端,使得用户在整个内容完成渲染之前可以先看到页面的部分内容,即不需要等服务端渲染完路由下的整个工作页面再显示,极大优化了页面的加载速度
优点:
- 数据获取:服务器组件允许你将数据获取移至服务器端,更接近数据源。这可以通过减少获取渲染所需数据的时间和客户端需要发起的请求数量来提升性能。
- 安全性:服务器组件允许你在服务器上保留敏感数据和逻辑,如令牌和 API 密钥,而不会有暴露给客户端的风险。
- 缓存:通过在服务器上渲染,结果可以被缓存并在后续请求和不同用户之间重复使用。这可以通过减少每个请求中的渲染和数据获取量来提高性能并降低成本。
- 性能:服务器组件为你提供额外的工具来优化基准性能。例如,如果你从一个完全由客户端组件组成的应用开始,将 UI 中非交互式的部分移至服务器组件可以减少所需的客户端 JavaScript 量。这对于使用较慢网络或性能较弱设备的用户来说很有帮助,因为浏览器需要下载、解析和执行的客户端 JavaScript 更少。
- 初始页面加载和 首次内容绘制 (FCP):在服务器上,我们可以生成 HTML 让用户立即查看页面,而无需等待客户端下载、解析和执行渲染页面所需的 JavaScript。
- 搜索引擎优化和社交网络分享性(SEO):渲染的 HTML 可以被搜索引擎机器人用来索引你的页面,也可以被社交网络机器人用来生成页面的社交卡片预览。
- 流式传输:服务器组件允许你将渲染工作分块,并在准备就绪时将它们流式传输到客户端。这让用户可以更早地看到页面的各个部分,而无需等待整个页面在服务器上渲染完成。
缺点:
- 需要服务端动态渲染的页面,增加了服务端的计算量,尤其在高并发的情况下,增大了服务器压力
- 依赖网络速度和服务器性能,无法做前端离线应用,页面交互体验低于客户端渲染
- 开发复杂度较高,需要为服务端和客户端分别设计代码逻辑(如路由、数据获取),增加了开发难度。
- 需要处理更多边界情况,例如如何在服务端正确初始化全局状态。
服务端组件渲染 vs 传统的服务端渲染SSR (Server-Side Rendering) 的区别:
- 服务端渲染:是关于在服务器上渲染整个初始页面。它将完整的 HTML 和 JavaScript 发送到客户端,然后客户端对其进行合并以使页面具有交互性。
- 服务端组件渲染:服务器上渲染单个组件。这些组件以 HTML 和 JavaScript 的混合形式发送到客户端,并集成到客户端 React 树中以显示数据并提高性能。
客户端组件(Client Components)
常见的有:react、vue、angular 框架打包出来的内容。
一个空<div>的html文件为入口,下载引入js文件,页面渲染由浏览器解析执行js文件来完成。
在Next.js中,默认是服务端渲染,如果需要使用客户端渲染,需要在页面文件的顶部使用"use client"声明服务器组件和客户端组件模块之间的边界,且所有导入到该文件中的其他模块(包括子组件)都被视为客户端包的一部分。
在Next.js中,客户端组件的渲染方式会根据请求类型分为两种方式:
-
完整页面加载(首次访问应用程序或浏览器刷新触发的页面重新加载):
为了优化初始页面加载,Next.js 将使用 React 的 API 在服务端为客户端和服务端组件渲染静态 HTML 预览。这意味着,当用户首次访问你的应用程序时,他们将立即看到页面内容,而无需等待客户端下载、解析和执行客户端组件 JavaScript bundle。在服务端
- React 将服务端组件渲染为一种特殊的数据格式,称为 React 服务端组件 Payload (RSC Payload),其中包括对客户端组件的引用。
- Next.js 使用 RSC Payload 和客户端组件 JavaScript 指令来在服务端渲染路由的 HTML。
在客户端
- HTML 用于立即显示路由的快速非交互式初始预览。
- React 服务端组件 Payload 用于协调客户端和服务端组件树,并更新 DOM。
- JavaScript 指令用于 hydration 客户端组件并使其 UI 具有交互性。
*注:Hydration 是将事件监听器附加到 DOM 的过程,以使静态 HTML 具有交互性。在幕后,hydration 是使用
hydrateRootReact API 完成的。 -
后续导航:
在后续导航中,客户端组件完全在客户端解析执行已下载完成的js文件,而非服务端渲染的 HTML。
这意味着客户端组件 JavaScript bundle 会被下载和解析。一旦 bundle 准备就绪,React 将使用 RSC Payload 来协调客户端和服务端组件树,并更新 DOM
优点:
- 交互性:客户端组件可以使用状态、效果和事件监听器,为用户提供即时反馈并更新 UI。
- 客户端组件可以访问浏览器 API。
缺点:
- 搜索引擎爬虫无法抓取页面,不适合SEO
- 依赖用户设备性能,性能较差的手机影响复杂渲染,如动画、高计算量页面
- 客户端信息均为可见信息,缓存数据信息安全问题受到影响
客户端组件 vs 传统客户端渲染CSR(Client-side Rendering):
- 客户端渲染:首屏加载时需要等待所有静态资源文件下载完成,由浏览器解析js文件渲染出页面,白屏时间较长。
-
客户端组件:优化了客户端渲染白屏时间较长这一问题,采用了增量静态再生ISR(Incremental Static Regeneration)模式,首屏已由服务端渲染,可直接显示,后续页面回归到服务端渲染
注:对于按需 ISR 请求,中间件不会被执行,middleware中的路由逻辑不会生效
混合模式
服务端组件与客户端组件比对.png
Next.js v13以上版本支持混合模式:交错使用客户端和服务器组件
从根布局(服务器组件)开始,可以通过添加
"use client" 指令在客户端上渲染组件的某些子树。在这些客户端子树中,仍然可以嵌套服务器组件或调用服务器操作
混合模式注意事项:
-
在请求-响应的生命周期中,代码从服务器移动到客户端。如果需要在客户端访问服务器上的数据或资源,将向服务器发出新的请求 - 而不是来回切换。
-
当向服务器发出新请求时,所有服务器组件首先被渲染,包括那些嵌套在客户端组件内部的组件。渲染结果(RSC Payload)将包含对客户端组件位置的引用。然后,在客户端上,React 使用 RSC Payload 将服务器和客户端组件协调到单个树中。
-
由于客户端组件在服务器组件之后渲染,因此不能将服务器组件导入到客户端组件模块中(因为它将需要返回服务器的新请求)。相反,可以将服务器组件作为
props传递给客户端组件。
更多参考 Next.js混合模式不支持的模式和Next.js混合模式支持的模式部分。
参考文档:
nextjs 渲染机制
掌握 Next.js 渲染机制:如何在 CSR、SSR、SSG 和 ISR 中做出最佳选择
React Server Components vs Server-Side Rendering
react hydrateRoot












网友评论