大家好,我卡颂。
有一句话相信大家都听过:
取代泡面的,并不是更高级的泡面,而是外卖的兴起
在前端领域,也存在同样的现象。作为前端缓存库中的佼佼者,React-Query
一直拥有大量受众,官方推出的React-Query
课程都卖出了8w+份。
但就是这样一款能打的产品,居然有被淘汰的风险,这究竟是为什么?
欢迎加入人类高质量前端交流群,带飞
前端缓存库的本质
React-Query
的定位是前端缓存库。如果从前端的视角来理解这个库,可能会认为它是axios
加强版。
但要理解这个库的本质,其实需要我们从后端的视角出发。
在后端看来,后端负责提供数据,前端负责展示数据,那么:
- 数据更新后,前端应该如何渲染?
- 数据失效后,前端应该如何渲染?
本质来说,这是个数据/缓存同步的问题,只不过在SPA
时代,这个问题刚好交给前端解决而已。
但是,后端天生离数据更近,解决这个问题更有优势。所以当渲染任务逐渐移向后端,React-Query
(或类似的库)便逐渐失去市场。
总结来说:取代React-Query
的,并不是更先进的竞品,而是他存在的土壤正在逐渐消失。
SSR技术的更迭
这里说的渲染任务逐渐移向后端就是指SSR
(服务端渲染)。但是,SSR
出现很多年了,为什么之前没有说要取代React-Query
?
这是因为,传统的SSR
主要应用在数据的首屏渲染。当首屏渲染完成,数据的后续同步操作还是发生在前端。
所以,React-Query
还是有用武之地。
类似的,在全栈框架Next.js
中,也推荐在CSR
(客户端渲染)时使用同团队开发的缓存库SWR
用于数据的同步操作。
但是,随着SSR
框架开始支持序列化数据,这一切都变了。
序列化数据的意义
在React
中,对于如下JSX
:
const name = "卡颂";
<p>你好,{name}</p>
在传统SSR
中,经由后端处理后,传递给前端的是如下HTML
结构:
<p>你好,卡颂</p>
HTML
结构可以直接渲染,很方便,但也失去了灵活性(不好更新)。
所以传统SSR
主要应用在首屏渲染这样的一次性过程。
在React Server Component
中,同样的JSX
结构经由后端序列化后,传递给前端的是Content-Type
为text/x-component
的如下数据结构:
0:["$@1",null]
1:["$","p",null,{"children":["你好,卡颂"]}]
这种数据结构有2个特点:
- 是序列化数据,反序列化后
React
可以识别 - 每行一条数据,方便流式传输
序列化数据可以显著提高SSR
的灵活性。
之所以这么说是因为,之前的SSR
只能返回HTML
结构,所以SSR
主要用于HTML
从0到1的首屏渲染。
现在,SSR
支持序列化数据。前端框架能够识别SSR
的结果,就能操作这个结果进行细粒度的HTML
更新。
把这个模型套在数据同步的场景:
- 之前,数据同步的逻辑主要发生在位于前端的
React-Query
中 - 现在,数据同步的逻辑发生在后端
既然数据同步的逻辑发生在后端,显然就不需要运行在前端的React-Query
了。
而且,序列化数据方案还有个好处 —— 凡是能够序列化的模块,都能将逻辑放在后端执行。
虽然React Server Component
直译叫服务端组件,看起来最小可序列化的模块应该是组件。
但是,只要遵循规范,其实函数作用域也能作为序列化的模块。
比如,在如下Next.js
代码中,AddToCart
组件在前端渲染,addItem
方法的逻辑是操作数据库的后端逻辑:
import { cookies } from 'next/headers';
export default function AddToCart() {
async function addItem(data) {
'use server';
const cartId = cookies().get('cartId')?.value;
const id = await saveToDb({ cartId, data });
return id;
}
return (
<form action={addItem}>
<button type="submit">加入购物车</button>
</form>
);
}
当点击按钮,触发后端执行addItem
方法,方法的返回值会以RSC
的序列化数据的形式返回给前端。
总结
除了RSC
的序列化数据,Qwik
是另一款应用序列化数据的SSR
框架。
这些框架的理念都是 —— 后端优先。即:业务逻辑如果能放在后端,那就放在后端。
没曾想,随着这些全栈框架的爆发,前端缓存库React-Query
成为受伤最重的那个。
这就是所谓的 —— 毁灭你,与你何干。
网友评论