什么是 RSC?
前段时间 React 团队公布了一项用于解决 React 页面在多接口申请下的性能问题的解决方案 React Server Components。当然该计划目前还在草案阶段,官网也只是发了视频和一个示例 demo 来阐明这个草案。
React Server Component 是一种编写 React 组件的办法,该组件在服务器端出现,目标是进步 React 应用程序的性能。
RSC 呈现背景?
在官网的视频中阐明了次要起因是因为大量的 React 组件依赖数据申请之后能力做渲染。如果是这样,那么每个组件本人去申请数据的话会呈现子组件要等父组件数据申请实现,到渲染子组件的时候才会开始去申请子组件的数据,也就是官网所谓的 WaterFall 数据申请队列的问题。而将数据申请放在一起申请又十分不便于保护。呈现了一个两难的问题。
RSC 如何解决组件依赖数据渲染的问题?
既然组件是依赖数据做渲染的。那为什么接口不间接返回渲染后的组件呢?所以他们提出了 Server Components 的解决方案。计划的大略就是将 React 组件拆分成 Server 组件(.server.tsx)和 Client 组件(.client.tsx)两种类型。其中 Server 组件会在服务端间接渲染并返回。
RSC 和 SSR 有什么区别?
在服务端渲染在返回,就会想到 SSR,哪他们有什么区别了。相比 SSR 将组件在服务端渲染成填充内容的 HTML 字符串,并在客户端 hydrate 后应用。Server Components 更像咱们的在客户端写的一般组件一样,只不过他的运行环境是服务端。
SSR 与初始化相干
在应用 SSR 时,您将 HTML 渲染好发送给客户端,而后加载 React JS,一旦加载了 JS,应用程序就复原成了客户端的 React 应用程序,改应用程序被”水化“了。
意味着,SSR 的应用程序在初始化之后就不是 SSR 所领有的旧的应用程序,在 SSR 中,除了您的第一页加载是纯 HTML 之外,您的所有组件依然都是客户端组件!
RSC 始终在服务端
React Server 组件始终在服务器上出现。这些可能是从后端获取某些数据的组件,因而将这些组件的出现与正在获取的数据并置在一起是有意义的。每当须要从新渲染这些组件时,它们就会从服务器中从新提取并合并到现有的客户端 React 组件树中。最酷的是,即便咱们从服务器中从新获取视图的某些局部,客户端状态仍会保留。
RSC 组件更可能减小软件包大小
因为 SSR 应用程序是对于初始页面加载的,因而客户端可能会在浏览您的应用程序时最终下载所有依赖项.RSC 组件则这些依赖关系将始终仅存在于服务器上,因为这些 React Server 组件在出现之前不会交付给前端。
如何应用 RSC
官网 Demo
RSC 劣势
人造更靠近后端
比拟是在服务端渲染之后返回给客户端。任何其余数据源只须要通过 React 提供的 API 简略封装,使其反对 Suspense,就能接入 ServerComponent 中。人造更靠近后端。
解决 waterfall
RSC 以流的局势传递给客户端
0 打包体积
这可能比拟理想化,或者说在一些场景是能够的,为什么了?举一个例子:
假如咱们开发一款 MD 编辑器。服务端传递给前端 MD 格局的字符串。
咱们须要在前端引入将 MD 解析为 HTML 字符串的库。这个库就有 206k。
import marked from 'marked'; // 35.9K (11.2Kgzipped)
import sanitizeHtml from 'sanitize-html'; // 206K (63.3K gzipped)
function NoteWithMarkdown({text}) {const html = sanitizeHtml(marked(text));
return (/* render */);
}
只须要简略将 NoteWithMarkdown 标记为 ServerComponent,将引入并解析 MD 这部分逻辑放在服务端执行。其实就是说把这放在服务端不须要客户端去 bundle 文件,来达到升高打包体积的问题。
主动代码宰割
通过应用 React.lazy 能够实现组件的动静 import。
之前,这须要咱们在切换组件 / 路由时手动执行。在 ServerComponent 中,都是主动实现的。
加重客户端渲染压力
同 SSR 一样,把加载 -> 获取数据 -> 在渲染,这样一个串行的模式,变成一个服务端一次操作的并行模式,来达到加重客户端渲染压力。
RSC 可能带来的问题
接口返回
失常状况下:加载组件,接口返回组件须要的数据,进行视图的更新渲染。
RSC:将组件的加载和数据的加载合二为一,缩小了 bundle 的体积,然而体积本义到了接口返回中,特地是在相似列表这种有分页的申请中,这种劣势会更显著。明明组件只须要在初始的时候进行加载,然而因为被交融进接口里了,每次接口都会返回冗余的组件构造,这样也不晓得是好还是不好。可能后续须要优化一下接口二次返回只返回数据会比拟好。
服务器老本问题
将客户端渲染行为迁徙到服务端时候势必会减少服务端的压力,用户量上来之后这块的老本是成量级的在减少的。对于这个问题,官网提供的回复是随着服务器的老本升高势必 Server Components 带来的劣势会对消这块的劣势。从以后来看,这个老本还是低廉的。
针对 RSC 解决的问题,有没有更好的解决方案?
RSC 解决的问题:接口申请扩散在各组件中带来的子组件的数据申请须要期待父组件申请实现渲染子组件时能力开始申请的数据申请队列问题。
其实是有的,那就是在写法上进行优化,举个例子:
import React, {useState, useEffect} from 'react';
import ReactDOM from 'react-dom';
function App() {const [data, setData] = useState([]);
useEffect(() => {fetchData.then(setData);
}, []);
return (
<div>
{!data.length ? 'loading' : null}
<Child data={data} />
</div>
);
}
function Child({data}) {const [childData, setData] = useState([]);
useEffect(() => {fetchChildData.then(setData);
}, []);
if(!data.length) {return null;}
return (<div>{data.length + childData.length}</div>
);
}
ReactDOM.render(<App />, document.querySelector('#root'));
如示例代码所示,只有加载组件,然而在无数据状况下不返回 DOM 也是能够做到子组件的数据先申请而无需期待的。当然这种须要认为的在写法上进行优化,但我也依然认为比大费周章的去做 Server Component 要好很多。
RSC:RFC
RFC
在 RSC 的 RFC 来看,有人赞成,也有人拥护。大部分人对 Server Component 还是持不赞成的态度的,认为它可能并没有像 React Hooks 那样解决业务中的理论痛点。就目前裸露的提案,我集体也感觉 Server Component 是弊大于利的。