xxleyi / learning_list

聚集自己的学习笔记
10 stars 3 forks source link

React Server Components 札记 #269

Open xxleyi opened 3 years ago

xxleyi commented 3 years ago

image

React 团队又搞了个重磅炸弹:服务端组件,React Server Components。

下面是一些个人的理解与思考。

什么是 RSC 呢?就是某种类型的组件在服务器上就被 render 掉,产出是 React runtime 可以理解的「某种描述 UI 的数据」,然后通过网络请求发给客户端,客户端上的 React runtime 会把这种描述 UI 的数据严丝合缝的嵌入到客户端已有的 UI 数据中,最终渲染成真实的浏览器 DOM 结构,交由浏览器进一步渲染成用户肉眼可见的 UI。

早在 React 之前,传统的服务端就可以通过 template 动态生成 HTML(这是浏览器可以直接理解的一种描述 UI 的数据), 然后将 HTML 发给浏览器,然后浏览器将其渲染为真实的浏览器 DOM 结构,并进一步渲染成用户肉眼可见的 UI。

在 React 这类聚焦客户端渲染的前端框架横扫 Web 前端的同时,人们依然有着服务端渲染的需求,这就是 SSR,一般是为了加快首屏渲染速度和搜索上的 SEO 优化。其背后的技术底子也是先在服务端渲染出 HTML。

RSC 和这些已有的技术是不是很像?确实比较像,但又有微妙而本质的区别。服务端通过 template 动态生成 HTML 文件时,会阻塞式的访问数据库,得到各种最新数据,然后将其填充到 template 中,从而生成 HTML 格式的数据。HTML 是静态 UI,而且浏览器只能使用覆盖式更新的方式渲染最新的 HTML 数据。

RSC 呢?服务端渲染自定义的组件,产出是 React 自己可以进一步消费的「某种描述 UI 的数据」,与 HTML 的本质不同在于,它包含更多信息量,可以降维到 HTML,意思是 SSR 的能做的,RSC 也能做,但真正的杀手锏是:它可以和客户端现有的状态组件进行合并渲染,更新 UI 的同时,保留客户端现有 state

本质上,RSC 的到来,意味着 UI = f(data) 这一 React 的核心设计正式打通客户端和服务端。注意,不是简单的支持服务端,而是将客户端和服务端联合在一起:组件不再受限于客户端或服务端,而是可以自由移动,当然需要付出一些精力进行合理改造。但好消息是,据 Facebook 自己内部的实践结果看,共享组件的比例是绝对的大头,而共享组件是无需额外努力,就可以在客户端和服务端之间自由移动的一类组件。这类组件既没有自己的 state,也不需要使用外部数据源,看似是无名之辈,但数量却最为庞大。

RSC 的到来,也让我们可以重新审视组件中的 props 和 state:

换言之:因为 RSC 的到来,将会有相当一部分的 state 能够直接以 props 的形式存在,而无需在客户端通过 useEffect 或 componentDidMount 进行一次中转。组件可以在客户端和服务端之间的自由流动,直接体现在 state 和 props 之间的自由流动。

不得不感叹,聚焦于 UI = f(data) 的 React 坚持为自己和开发者保留足够的自由,坚决不引入任何非必要的语法糖和小打小闹式的优化,潜心搞大事情。于是,搞出了 hooks,搞出了 fiber 渲染引擎下的并发模式,搞出了并发模式下的服务端组件,但这所有的一切依旧在 UI = f(data) 这个核心的数据转换之内,在严格保留强一致性的基础上,扩宽自由边界的同时,也提供了越来越友好、顺畅的开发体验。

React 抓住数据转换这一核心,围绕这个核心的数据转换设计并实现一系列的编程方案,UI 中最关键的 state 部分从最开始寄居在 class 实例,到后来寄居于 React Fiber 节点,到现在其中的一部分又可以直接寄居于服务端的持久化存储系统中,比如 Redis, MySQL, MongoDB, 甚至 filesystem 和其它后端服务的数据 API。

至此我们也可以发现,state 无非就是两类:

这两类正好完美对应客户端和服务端。整个 Web 的发展历史也像一个钟摆:

总结:RSC 给了开发者把一部分 state 放到服务端处理的能力和自由,代价就是耗费更多服务器资源和更多的心智负担。