从 "use client" 引出RSC与Next的重新认识

引子

起因是这样的,今天早上在群里看到有个小伙伴发了这样一张截图,并表示疑惑:“我原来觉得我懂RSC,看他们吵这个我又看不懂了。”
Image
因为这种截图,群里产生了激烈的讨论,主要是关于何时使用 "use client",以及有的小伙伴和我一样关于 RSC 产生了些许的疑问。那我们往下看看吧。

use client

在文章看头的截图里,dan 说只有在 server / client 边界时使用 "use client"才是必要的。我们可以浅看下 dan 说的例子,如果不是太懂,可以看看下面我的阐述。

为什么需要使用

借鉴next官网的原话:
Client Rendering 的好处:

使用时机

我们先看一个nextjs官网的截图。
Image
注意这句话:use client 被使用在声明一个 Server ComponentClient Component 模块之间的边界。意味着一个文件中定义了use client,那么它导入的所有模块,包括子模块都是 Client bundle,也就表示这些模块不需要再在其中定义use client,这就是对 dan 说的边界和不需要使用use client的完美阐述。

重新了解Next

Next自从13版本后,使用App Router将内置使用React Server ComponentsRSC)。
Image

Server Components

React 服务器组件允许您编写可以在服务器上渲染和选择性缓存的 UI。在 Next.js 中,渲染工作被路由段进一步分割,以实现流式渲染和部分渲染,并且存在三种不同的服务器渲染策略:

在服务器上进行渲染工作有几个好处,包括:

如何渲染

在服务器上,Next.js 使用 React 的 API 来编排渲染。渲染工作被分成多个Chunk:按单独的路线段和 Suspense Boundaries

每个Chunk都分两步渲染:

  1. React 将服务器组件呈现为一种特殊的数据格式,称为React 服务器组件有效负载(RSC Payload)
  2. Next.js 使用 RSC 有效负载和客户端组件 JavaScript 指令在服务器上呈现HTML 。

然后,在客户端:

  1. HTML 用于立即显示路线的快速非交互式预览 - 这仅适用于初始页面加载。
  2. React 服务器组件有效负载用于协调客户端和服务器组件树,并更新 DOM。
  3. JavaScript 指令用于Hydrate客户端组件并使应用程序具有交互性。

What is the React Server Component Payload (RSC)?
The RSC Payload is a compact binary representation of the rendered React Server Components tree. It's used by React on the client to update the browser's DOM. The RSC Payload contains:

  • The rendered result of Server Components
  • Placeholders for where Client Components should be rendered and references to their JavaScript files
  • Any props passed from a Server Component to a Client Component

Client Components

要使用Client Components,需要添加use Client,关于它的使用方法前文已介绍,不再赘述。

这里我之前一直有一个误区,认为Client Components是在页面返回后才加载其组件UI的,但今天仔细回顾才发现这种想法是错误的。下面将详细介绍。

如何渲染

在 Next.js 中,客户端组件的渲染方式有所不同,具体取决于请求是完整页面加载(对应用程序的初始访问还是浏览器刷新触发的页面重新加载)或后续导航的一部分。

整页加载

为了优化初始页面加载,Next.js 将使用 React 的 API 在服务器上为客户端和服务器组件呈现静态 HTML 预览。这意味着,当用户第一次访问您的应用程序时,他们将立即看到页面的内容,而无需等待客户端下载、解析和执行客户端组件 JavaScript 包。

注意:
这里明确说明了:为both Client and Server Components呈现静态HTML预览,(我理解的是UI会服务器端同服务器组件一同返回,事件那些在客户端加载,因为 use client 是给webpack插件做标记用的,类似React.lazy的效果)。

后续导航

在后续导航中,客户端组件完全在客户端上呈现,而不需要服务器呈现的 HTML。

这意味着客户端组件 JavaScript 包已下载并解析。一旦包准备好,React 将使用 RSC Payload 来协调客户端和服务器组件树,并更新 DOM。