让我们面对现实吧,React Server Components并不是Next或React最受欢迎的功能。许多开发人员实际上已经在心理上屏蔽了它们,并决定通过在所有组件顶部添加use client
来假装它们不存在。
但这不仅是错误的,他们也错过了很多好处。
在本文中,我将试图说服你开始使用它们,所以开始吧。
要理解这些“新”组件的好处,首先你必须了解它们的工作原理。
如果你一直是前端开发人员,这可能是你需要的缺失的一块,所以请注意听。
RSC在服务器上执行(因此它们的名称中有“server”一词)。但这到底意味着什么?
这意味着框架(比如NextJS)将执行以下操作:
-
它将确定页面中的哪些组件(包括页面本身)实际上是服务器组件。
-
对于每个组件,它将加载React的服务器版本并执行它们。
-
每个组件将输出一个HTML作为结果,并且该HTML将在发送到浏览器的捆绑包中占据其位置。
捆绑包称为React Server Component Payload,浏览器将在其中找到:
-
从执行每个RSC得到的实际HTML。
-
HTML中的占位符,用于需要在浏览器上进行注水的客户端组件。
-
可选地,如果有任何从服务器组件传递到客户端组件的props,这些props也将在payload中。
就是这样。
这也是一个非常常见的问题。我理解这种困惑,但不,RSC和SSR不是同一回事。
虽然SSR(服务器端渲染)专注于在服务器上渲染整个应用程序,然后将其发送到客户端进行注水,但RSC仅关注单个组件。它们在更细粒度的级别上优化渲染过程。
所以现在让我们继续“为什么你应该使用RSC”。
你是否曾经需要从React组件中获取数据?
通常的做法如下:
-
如果可以的话,你编写数据获取逻辑直接从数据源查询数据(比如外部API)。
-
或者你在服务器端创建一个内部端点,实际上查询数据源(比如数据库或外部API),并编写数据获取逻辑来访问你的内部端点。
如果你选择第一种方式,缺点如下:
-
由于你从浏览器查询外部API,可能会遇到CORS问题。
-
你无法查询某些数据源,比如数据库或从磁盘读取文件。
-
你将数据获取逻辑暴露给用户,潜在地泄露不应该被最终用户(或潜在攻击者)看到的代码和逻辑。
-
你将数据源的许多错误处理逻辑与UI组件耦合在一起。
如果你选择第二种方式,虽然确实解决了安全方面的问题,并且不再将数据获取错误处理逻辑与UI组件耦合在一起,但你仍然需要编写额外的代码来创建内部API端点。
但如果你能同时拥有两全其美呢?这就是RSC的作用所在!
使用React Server Component,你可以编写如下组件:
async function getUserData(){
//你的数据获取逻辑放在这里...
}
async function MyComponent() {
let data = await getUserData()
if(!data) {
return (<div className="error-msg">用户未找到!</div>)
}
return (
<div>
{data.username}
<DeleteUserButton id={data.id} />
</div>
)
}
那么,我们在这里做了什么?让我们分解一下:
-
我们有一个组件,它不使用任何交互式代码(没有DOM API,没有事件处理程序,没有浏览器API等)。
-
我们有一个组件,它不使用副作用或状态(没有调用
useEffect
或useState
钩子)。 -
我们有一个组件,它只是调用一个常规函数来获取一些数据,然后使用简单的HTML标签显示该数据。
-
我们还有一个组件调用了另一个名为
DeleteUserButton
的组件,该组件将具有事件处理程序(比如onClick
处理程序),这使它成为一个客户端组件。
我们的服务器组件比我们讨论过的其他选择更简单,因为:
-
我们不需要创建全新的内部API端点。
-
我们不需要将错误处理逻辑与UI组件耦合在一起(这是一个后端组件)。
-
使用这种方法,我们不会遇到任何CORS问题。
-
你可以从
getUserData
函数中查询任何数据源。无论是数据库、外部API还是本地文本文件,你都可以从任何你想要的地方获取数据。
总而言之,到目前为止,这是一个巨大的胜利,但让我们继续!
首先免责声明:只有在你做对了的情况下,这才有效果。如果你仍然搞砸了,仅仅使用RSC并不能比使用客户端组件精心制作的UI获得更好的性能。
有了这个前提,让我们了解一下这个原因的含义。
记住,RSC在服务器上渲染,所以我们首先注意到的是浏览器不需要做任何工作来渲染DOM的那部分。是的,它必须在从服务器接收到它们后将这些节点添加到整个树中,但没有涉及解析代码、动态创建HTML元素,然后更新DOM的JavaScript。
这种模型允许你将渲染代码所需的处理能力转移到服务器上。这对于非常复杂的应用程序特别有用,可以将大部分组件转换为服务器组件。
从你在浏览器上不再执行的额外工作中获得的另一个好处是,UI可以更快地加载并更早地向最终用户显示信息。这反过来可以被视为对你的应用程序用户体验的改进。你的用户在等待首次有意义的绘制的时间更短了,这发生在浏览器开始向用户显示任何有意义的内容时。
开始使用RSC的另一个非常有效的原因是简化客户端组件的逻辑。
换句话说,现在你可以停止将客户端组件视为存储UI业务逻辑的唯一位置。
现在,你可以将许多“繁重”的工作(如数据获取和数据处理)转移到RSC上,让客户端组件只处理实际的表示(UI)。
这将帮助你减小客户端组件的大小,从而减小每当需要渲染新组件时发送到客户端的捆绑包的大小。
通过添加服务器组件,你现在能够拆分你在仅客户端组件中的代码。你可以删除执行非UI相关逻辑的不必要代码,并将其移动到服务器上,同时保持渲染部分不变(几乎不变)。
你甚至可以删除不需要任何动态行为的整个UI组件(比如页脚),并将它们放在服务器上进行渲染。现在,你的UI代码库的规模突然大大减小了。
这也是一个巨大的胜利!
总结一下,React Server Components并不差,事实上,它们非常棒。但是一开始它们确实需要一些思维上的转变,特别是如果你以前没有做过后端编码。
它们为你的Web开发工作流带来了许多改进,但我确定的主要改进有:
-
你能够更轻松地进行数据获取/数据处理(并且更安全)。
-
你使用的工具可以通过小的改变为用户提供更好的UI/UX。
-
通过从客户端组件中删除非UI代码,你减少了UI代码库的复杂性。