这个由 React 官方博客[1] 发布于 今天(12-22)凌晨,他们是因为疫情都没法过圣诞了所以索性搞点有意思的?这还仅仅是个研究性质的东西,官方文章甚至简洁到直接丢个 视频[2],当然 RFC[3] 还算比较详细,时间充裕的可以完整看看,这里简单基于目前得到的信息总结下。我们基于官方 演示 DEMO[4] 部署了个 https://react-server-components.musicfe.dev/[5] ,可以对照着看。
解决什么问题
Dan 开门见山,丢出了我们业务开发中需要权衡三个点:体验(user experience)、可维护性(maintenance)、性能(performance),然后用一个例子来说明为什么这三个点很难权衡。
这是一个很常见的组件化组合,问题在于每个组件都需要不同的数据,但是就体验而言我们更希望这些组件的渲染尽量同时,而且如果关注性能的话,我们也会考虑并行的去 fetch 数据,于是我们通常会 fetch 逻辑放到顶层,然后通过 Props 或者 Context 传递下去。
这样会把可维护性变差,除了看起来恶心,每个组件从逻辑上就不那么解耦了,我们于是会考虑每个组件自己处理 fetch 逻辑。
这又会让体验变差,因为浏览器从服务端 fetch 数据是比较贵的 IO,抽象一下就是下面这样:
我们之所以需要从服务端 fetch 数据,是因为我们把所有渲染操作放到了客户端,那如果我们把部分渲染逻辑放服务端呢?
于是就有了 React Server Components!
跟 SSR 什么关系
React Server Components 这名字可能让人第一个想到是不是出了个官方的 SSR 方案?官方视频很少提到 SSR,是因为这个跟 SSR 就不是一个东西,理论上也可以混用。如果你仔细看我们部署 DEMO 的页面内容,会发现其实跟 CSR 没区别:
再点击侧面 Notes 组件时,会发现有异步请求,但是返回的内容是这样的:
当然,对 SEO 也没帮助。从这里也很容易知道,框架启动了后端服务,通过 /react
异步地输出页面内容,只是这个页面内容不是 HTML,是一个自定义的结构。之所以不是直接输出 HTML 猜测是因为需要做些高级的事,比如维持组件状态。
什么场景下使用
虽然 Dan 一开头就说了痛点,不过感觉还是不够痛,可能他只是为了引出话题。如果我们现有 Client Components 组件树是这样的话:
那么使用 Server Components 后就是这样:
是的,我们可以随意的混合使用两种组件。看到这里,你可能想到了,这不就是 Suspense + Lazy 的变种么?异步从 CDN 拉取组件后由客户端渲染变成了异步从服务端拉取基本渲染好的组件。那你可能会说,看起来也没啥好处嘛?考虑以下情况:
- 异步组件需要依赖比较多组件,这个 chunk 就会比较大
- 渲染比较耗 CPU,客户端可能会白屏或者掉帧
这些情况换成 Server Components 问题就会很容易解决了!不过这里少不了多出的服务器成本,就开发过程而言,相信未来在工具链完善的情况下,跟目前使用 Client Components 类似。
展望
个人还是很期待的,甚至有个大胆的想法,未来会不会出现一个公共服务,专门提供服务端组件,这或许是前端引入 BaaS 服务的又一个很好的点。
参考资料
[1]
官方博客: https://link.zhihu.com/?target=https%3A//reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html
[2]
视频: https://link.zhihu.com/?target=https%3A//www.youtube.com/watch%3Fv%3DTQQPAU21ZUw
[3]
RFC: https://link.zhihu.com/?target=https%3A//github.com/reactjs/rfcs/blob/2b3ab544f46f74b9035d7768c143dc2efbacedb6/text/0000-server-components.md
[4]
演示 DEMO: https://link.zhihu.com/?target=https%3A//github.com/reactjs/server-components-demo
[5]
https://react-server-components.musicfe.dev/: https://link.zhihu.com/?target=https%3A//react-server-components.musicfe.dev/