12月21日,有啥用?React团队公布了一个新的有啥用?提案Server Components。 伴随这个提案同时发出的有啥用?,还有一个小时的有啥用?视频讲解[1]、可供运行的有啥用?Demo[2]、详尽的有啥用?介绍。 可见,有啥用?React团队很重视这个提案。有啥用?本文会从如下方面讲解: ServerComponent是什么 一句话概括: Server Components是在服务端运行的React组件。 咦?有啥用?这和服务端渲染(SSR)有什么区别? 相比SSR将组件在服务端渲染成填充内容的HTML字符串,并在客户端hydrate后使用。有啥用?Server Components更像我们的有啥用?在客户端写的普通组件一样,只不过他的有啥用?运行环境是服务端。 我们可以将组件按照功能分为: 举个例子,Note组件是有啥用?容器组件,他负责请求并缓存数据。NoteEditor是香港云服务器渲染note数据并执行用户交互的交互组件。 如例子所述,我们可以通过在useEffect中发起请求并将返回的数据保存在state中。 这种「请求-渲染」模式会遇见被称为waterfall的问题: 就像一节一节的瀑布往下流水,NoteEditor需要等待Note请求note成功后才能开始渲染。 当交互组件依赖的数据源越多,waterfall问题会更明显。 理论上,如果React足够聪明,就能在服务端执行容器组件的渲染逻辑,在客户端执行交互组件的渲染逻辑。 按照这样的理念,如下这棵完全在客户端渲染的组件树: 可以拆分为:在服务端运行的容器组件和在客户端运行的交互组件。 其中在服务端运行的容器组件就是Server Component。 ServerComponent的意义 既然ServerComponent在服务端运行,天然更接近各种IO(请求数据库、读取文件、缓存...)。 上面的源码库例子完全可以直接从数据库获取note数据,同时借助Suspense,采用同步的写法。 天然更接近后端 任何其他数据源只需要通过React提供的API简单封装,使其支持Suspense,就能接入ServerComponent中。天然更接近后端。 解决waterfall 区别于SSR传输的HTML字符串。ServerComponent会将Note组件及其从IO请求到的数据序列化为类似JSX的数据结构,以流的形式传递给前端: 客户端在运行时直接获取到填充了数据的流,并借助Concurrent Mode执行流式渲染。 0打包体积 假设我们开发一款MD编辑器。服务端传递给前端MD格式的字符串。 我们需要在前端引入将MD解析为HTML字符串的库。这个库就有206k。 通过ServerComponent我们怎么解决这个问题呢? 只需要简单将NoteWithMarkdown标记为ServerComponent,将引入并解析MD这部分逻辑放在服务端执行。 ServerComponent并不会增加前端项目打包体积。这个例子中,一次性为我们减少了前端206K (63.3K gzipped)的打包体积以及解析MD的时间。 自动代码分割 通过使用React.lazy可以实现组件的动态import。高防服务器之前,这需要我们在切换组件/路由时手动执行。在ServerComponent中,都是自动完成的。 在上面动图中,左侧列表是ServerComponent,当点击其中卡片时,组件对应数据会动态加载。 更好的ahead-of-time (AOT)优化 Vue作为一门使用模版语言的框架,模版语言的固定写法使其能在编译时针对模版内容作出优化。 由于JSX仅仅是JS的语法糖,React很难在编译时做出优化。 ServerComponent对组件提出了更多限制(不能使用useState、useEffect...)。这些限制从侧面为AOT提供更多优化线索。 ServerComponent的使用 下面我们通过改写一个记事本组件讲解ServerComponent的使用: Note组件的主要功能是根据props传入的id请求对应的note数据。 NoteEditor用于展示及修改note。 其中fetchData方法用于获取数据,数据的加载中状态由组件外的Suspense完成。 可以看到,交互部分由NoteEditor完成,Note主要功能是获取并传递数据。 接下来我们将Note变为ServerComponent。 有3点需要注意的改动,我们依次了解下: 总结 太阳底下没有新鲜事。早期前端交互简单,仅仅作为服务端的View层。 随着前端交互变复杂,出现了前端框架主导的客户端渲染(CSR)。 为了解决首屏渲染速度、SEO问题,出现了服务端渲染(SSR),又回到了曾经作为View层的起点,只不过控制的粒度更细。 ServerComponent提案的出现,预示着React的长远目标:将对View层的控制细化到组件级别。 为什么是「长远目标」?ServerComponent落地的大前提是Concurrent Mode生产环境稳定,让我们一起期待2021年吧。 参考资料 [2]Demo:https://github.com/pomber/server-components-demo/