您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

React:我们即将和后端 API 告别?

时间:2022-08-01 09:47:04  来源:  作者:Java机械师

前言

2020 年底,React 公布了一个全新的特性:Server Components,当时它还处于调研和试验阶段,并没有正式发布,随着 React 18.0 版本的正式发布,Server Component 的脚步声也越来越近了,不出意外的话,应该会在今年的某个 React 18 的 minor 版本中正式发布。

Server Components 听起来好像并不那么激动人心,React 18 所发布的各种特性也似乎平平无奇,自从 Hooks 面世已经三年多过去了,React 似乎停滞了前进的脚步,只是在现有的基础上做些小修小补?

No。

Concurrent rendering(React 18 新带来的特性)是一种本质上的改变,它本身不像 Hooks 那样对开发体验有着近乎翻天覆地的变革,但是这种底层渲染能力/机制的调整,会带来非常非常多的可能性,例如:

Suspense、OffScreen、Server Components

这三种特性,目前都没有生产可用,但是等到未来他们正式发布并渐渐被大面积使用时,每一项特性都会带来非常显著的开发体验的提升。而如果让我从这些未来会出现的新特性中选一个最期待的,那毫不疑问会是 Server Component。

所以,Server Components 到底是什么?他会像当年的 Hooks 一样对整个 React 生态带来巨大的影响么?在我们回答这些问题之前,很有必要先解释一下 Server Components 是什么,又解决了什么问题。

注:下文中的很多内容受 Dan 和 Lauren 的这份 演讲视频 [1] 所启发,如果你想更深入的了解即将到来的 React Server Component,那么非常推荐这段视频 事实上,这篇文章并不是一份对 Server Components 的用法教学,也不会涵盖 Server Components 的每一处细节(甚至为了方便表述会有意地略过一些细节),因此, 在读下文之前,最好是对 Server Components 已经有所了解

背景:前后端分离

“前后端分离”是当下主流的 web 研发模式,后端存储数据,并把对数据的操作(增删改查)封装成接口,通过后端服务提供给前端,前端应用发送请求(例如 http 请求或者 rpc 请求)去调用后端提供的接口,从而获取到数据或者是对数据进行修改。

 

这可能是十几年以来非常普遍的研发模式了,也因此,我们被区分成前端开发和后端开发,各自负责着“楚河汉界”的一侧。我们在各自那一侧都做了非常多的优化、创新、突破,在后端,我们有容器化、微服务、SSR,在前端,我们有 code spliting、前端路由、React Hooks。

但是对于 API 层,我们似乎这么多年以来都未曾有过关注,即便是有,也仅仅是停留于 API 传输性能(例如 grpc)、API 的存在形式(例如 Restful 和 GraphQL)、API 的工程化管理(例如 Postman)。

并非是想说 API 一个邪恶而糟糕的设计,但是自从 Restful 的概念被提出以来,已经 22 年过去了,我们是不是应该在现在重新思考一下:

  • 以网络请求作为前后端的分界是最优解吗?
  • 如果没有 API,我们该如何架构和开发 Web 应用?

症结所在

让我们再回到刚刚的那张图,考虑一下 API 在带来职责分工明晰之外,同时也带来了哪些问题。

请求瀑布流(Waterfall)

就像 Remix [2] 首页上所展示的,基于 API 和嵌套路由的前端站点,在请求时会出现瀑布流的现象:

 

数据的之间可能是有前后的依赖关系,抑或是和组件强耦合在一起,需要等待组件的 bundle 加载完成之后才能发出请求,这些都导致了请求瀑布流现象的出现。

并发请求

后端希望实现小而美的接口,每个接口有独立的职责,例如:

  • getUser 获取用户信息
  • getSongs?page=12 获取歌曲列表
  • getNotifactions 获取通知列表
  • getFavoirateSongs 获取收藏的歌曲
  • getNewSongs 获取新发布的歌曲
  • getRecommendSong 获取今日推荐的歌曲及对应的文案
  • getSearchBarHotKeywords 获取热门的搜索词
  • getAdBanner 获取广告 banner 内容
  • getRecentSongs 获取最近听歌记录
  • getRecommendedPlayList 获取推荐的歌单列表
  • ……(实在太多了)

每一个接口,单独拿出来看都是合理的,但是放在一起,就会发现用户每次打开这样一个音乐 web App,都要发送至少十几个接口,对于一些稍微复杂一点的网页,首次加载就需要请求几十个接口也丝毫不奇怪。

每一个接口的请求,都会带来网络开销,甚至在有些环境下会有最大并发请求数量的限制(例如在支付宝客户端那的 rpc 请求),或许网络层的 automatic batching 可以解决这个问题,但是遗憾的是,在目前的技术体系内,这个问题并不好解决(这里没有写不能解决,是因为的确有一些可行的方案,例如 BFF、依赖网关来做接口聚合,但它们都引入的新的问题)。

前端包体积(Bundle size)

包体积已经是“现代”前端开发领域饱受诟病的一点了,动辄几百 k 的 js 文件,似乎已经背离了浏览器是用来“浏览”网页的初衷了。并不是说我们都要做一个浏览器原教旨主义者,但是如果网页能够在不损失用户体验和开发体验的前提下,恢复到非常轻量和快速的状态,难道不是一件好事么?

协作成本(沟通、逻辑感知和封闭)

在我个人看来,这是大型项目或需要长期维护的应用中最令人头疼的问题了。

假设我们现在有一个非常巨大的应用,需要有十几位开发者共同编写和维护,那如何分工?答案必然是先做模块化,我们把整个应用拆分成几个彼此尽量独立的模块,再由每个人或每几个人负责其中的一个模块。

模块化带来的好处是边界清晰(看到一个需求就能判断出来涉及到哪个或哪些模块做哪些改动)、职责明确(每个人都有自己确定的职责)、减少沟通成本(由于模块内部的逻辑是封闭的,不需要外部感知,所以可以降低沟通成本)。

对于前两点,目前的前后端分离架构都还是及格的,但对于第三点,我觉得基于网络请求接口的协作模式,在很多情况下并没有有效地做到逻辑内部封闭、减少需要前后端之间来回沟通的信息量。

举个例子,对于这样的一个页面:

 

看起来非常简单,一些信息的展示,加上一个充值按钮,这就是我最开始所设想的。

然而,随着这个项目不断的推进,我发现,原本以为是纯静态的标题文案,实际上是需要后端控制的,根据当前用户的所属人群来动态判断文案内容;我发现,由于前端金额计算的可靠性问题,折扣和实际支付相关的内容都是需要在后端预处理之后展示在前端的;

我发现,倒计时的参考时间是需要依靠后端返回的;我发现,按钮的文案、点击行为,是需要后端控制的,特别是按钮的点击行为,最终方案是后端返回一个枚举,前端根据这个值来 switch case 一下走不同的逻辑(例如下单、引导先进行注册和绑卡)……

为了阅读体验,我只是列举了其中随手想到的一小部分,如果总结一下,那就是,后端和前端并没有因为“前后端分离”而做到解藕,反倒是藕断丝连,剪不断理还乱。后端感知了过多的前端视图层逻辑,就像是发明了一套 DSL(DomAIn Specific Language),而前端则是要写一个针对这套 DSL 的解析器和渲染器。

回到我们刚刚提到的,模块化带来的好处。模块化能够降低沟通成本,有一个不可忽略前提,就是架构的合理性。模块化并非是降低沟通成本的本质原因,也并非所有的模块化实践都能带来沟通成本的降低。当前后端分离的实践成为一个僵硬的、死板的“规范”,那它还能真正起到多少降低沟通成本的作用?一个大大的问号。

Server Components

再次申明一下,下文是假设读者朋友已经对 Server Components [3] 有所了解

基于网络请求的 API 模型,有一个大大的前提假设,就是前端应用和后端应用是两个独立的应用,但是为什么一定要是这样?

或许我们可以让后端应用直接渲染 html,用户操作时,重新渲染一遍页面?这其实就是在 Restful 时代之前的架构,有很多弊端,特别是可交互性差,不然也就不会出现后来 Restful 的盛行了。

那再或许,我们可以让前端的 React 组件,运行在后端?

这就是 React Server Components。

一图胜千言,在现在的前后端分离模式下,后端提供接口,前端的 React 组件调用接口。

 

而如果后端可以运行 React 组件,直接渲染 React 节点树到前端,就不需要所谓的 API 的概念了。

 

后端运行 React 组件并不是什么新鲜事,我们在 SSR(Server Side Rending)早就习以为常了,但是需要特别注明的一点是,在 SSR 中,后端是运行了 React 组件,生成了一份初始状态的 html,但这份 html 是没有可交互性的,它只是为了让用户能尽早看到页面而做的一种改良式的、修修补补一样的优化。

而 Server Components 所带来的,是我们可以把同一个项目中,一部分的组件作为 Server Components,另一部分组件,作为 Client Components,因此我们可以既享受到后端内部调用带来的便捷、可维护性,又能保证页面的可交互性几乎没有任何妥协。

如果你用过 php 或 Django,那你肯定非常熟悉这种模式:后端直接渲染 html 内容,浏览器只负责显示,用户点击按钮,那就重新请求、重新渲染页面,如果页面上需要一些复杂的动态交互,比如让用户可以把一个列表展开/收起,或者是点击某个按钮之后展示一个模态框,那可以借助于 jQuery 来实现。

PHP + bootstrap + jQuery,现在,Server Components 就像是这套范式的升级版,可以被称为一种全新的“全栈”开发模式。

因为是在后端环境下,这些 Server Components 可以使用全部的后端能力,不管是中间件,还是其他后端微服务的调用,甚至是 db 的访问(当然可以直接跑 SQL,但是更好的实践是通过一个数据中间层),都可以实现。这样一来,我们就可以直接把数据从源头获取,放到 React 组件的上下文中,那自然就不需要传统意义上的 API 了。

更准确的说,API 并未消失,我们其实也不会和 API 就此说再见,而是让它换了一种形式。有模块化的地方,就会有 API,Restful 的 http 网络请求固然是 API,但中间件暴露出来的方法,浏览器提供的 Date 对象,node 提供的文件读取函数,db 提供的 SQL,这些全都是 API。

在这种新架构下,API 变成了后端里业务应用和上游服务之间的调用,变成了 Server Components 和 Client Components 之间的 props 传递,前者让 API 变得更加干净、更符合单一职责的原则,而后者让 API 变得自然到你几乎感知不到。

所以:

  • Server Components 允许我们不再按照 前端 - 后端 进行模块的拆分,而是依照 业务应用 - 底层服务 来进行更合理的模块拆分。从而可以理论上降低模块之间的沟通成本(因为目前还没有办法实践证明)。
  • 由于 Server Components 是在后端运行组件,直接通过网络传输给前端进行渲染,因此很多大体积的包(例如 markdown 渲染、html sanitize)都不需要在前端下载和运行,从而很大程度上降低包体积。
  • 由于底层 db 或上游服务的调用都是发生在后端内部的,因此即便出现并发请求,所带来开销也远远小于前端并发调用后端的 Restful API。
  • 同理,请求瀑布流的问题也会因为调用开销降低而消失或减轻。

想象

如果大胆想象一下的话,未来的研发模式可能这样的:

开发者将不会再区分前端和后端,而是区分为业务应用开发和上游服务开发。现在的后端开发将(真正地)不再需要关注视图逻辑,只聚焦于底层业务逻辑,为前端提供清晰好用、原子化的服务/接口;而现在的前端开发将会拓展到横跨前端和后端(代码运行环境上),负责的是在后端封装好的一个个原子化的底层能力上,构建视图层,而我们也需要一套全新的框架和基础设施,来适配 Server Components。

目前,Server Components 还没有正式发布,而即便正式发布之后,也还有长长的工程化落地的路要走,Server Components 增加了很多额外的限制,server、client、shared 的区分也可能会带来一些理解成本。缓存、性能、server 重新渲染时的增量更新策略、发布时的可灰度性和可回滚性、业务中边界情况的处理,还有很多的问题需要去解决,还有很多的未知尚未被验证。

参考资料

[1] 演讲视频:
https://www.YouTube.com/watch?v=TQQPAU21ZUw

[2] Remix: https://remix.run

[3] Server Components: https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html



Tags:API   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
构建 Web API 的两种流行选择:REST vs GraphQL
在 RESTful 和 GraphQL API 之间的选择取决于您的具体用例。RESTful API 适用于需要高可伸缩性的简单应用程序,而 GraphQL 则适用于具有不同数据需求的复杂应用程序。简介RES...【详细内容】
2024-01-09  Search: API  点击:(66)  评论:(0)  加入收藏
理解 Spark 写入 API 的数据处理能力
这张图解释了 Apache Spark DataFrame 写入 API 的流程。它始于对写入数据的 API 调用,支持的格式包括 CSV、JSON 或 Parquet。流程根据选择的保存模式(追加、覆盖、忽略或报...【详细内容】
2023-12-13  Search: API  点击:(154)  评论:(0)  加入收藏
如何设计安全的 API 调用?
我们在设计一个网站或平台的时候,经常需要向用户开放 API 访问。这样用户就可以程序化地调用一些功能,举几个例子: 交易所开放 API 让用户可以进行低时延的程序化交易, 微信公众...【详细内容】
2023-11-30  Search: API  点击:(176)  评论:(0)  加入收藏
Kubernetes API Gateway 1.0 上线,维护者提出了未来规划
作者 | Joab Jackson译者 | 王强策划 | Tina用户期待已久的 Kubernetes Gateway API 现已准备好投入生产环境,并附带一系列新的支持工具来帮助 K8s 管理员入门。Kubernetes G...【详细内容】
2023-11-14  Search: API  点击:(285)  评论:(0)  加入收藏
五 种 API 网关技术选型,yyds
本文准备围绕七个点来讲网关,分别是网关的基本概念、网关设计思路、网关设计重点、流量网关、业务网关、常见网关对比,对基础概念熟悉的朋友可以根据目录查看自己感兴趣的部分...【详细内容】
2023-11-07  Search: API  点击:(313)  评论:(0)  加入收藏
Envoy 基于文件和 API 的动态配置方式
前面我们和大家学习了 Envoy 的基础知识,使用静态配置来认识了 Envoy,但实际上 Envoy 的闪光点在于其动态配置,动态配置主要有基于文件和 API 两种方式。基于文件的动态配置Env...【详细内容】
2023-10-30  Search: API  点击:(310)  评论:(0)  加入收藏
使用 Kubernetes 检查点 API 进行容器的备份和恢复
Kubernetes v1.25 引入了容器检查点 API 作为 alpha 特性。这提供了一种在不停止容器的情况下备份和恢复运行在 Pod 中的容器的方式。此功能主要用于调试分析,但任何 Kuberne...【详细内容】
2023-10-10  Search: API  点击:(281)  评论:(0)  加入收藏
负载均衡器、反向代理、API 网关区别
简介您是否理解负载均衡器、反向代理和 API 网关等多样组件之间的差异?不确定哪个组件最适合您的 Web 应用程序?这些关键组件在现代 Web 架构中发挥着至关重要的作用,了解它们...【详细内容】
2023-09-27  Search: API  点击:(282)  评论:(0)  加入收藏
一文搞懂 API Endpoint
Hello folks,我是 Luga,今天我们来聊一下应用程序接口(API)生态相关的技术概念 - API Endpoint 。— 01 —到底什么是 API ? API ,即全称为 Application Prog...【详细内容】
2023-09-14  Search: API  点击:(236)  评论:(0)  加入收藏
探索 Gateway API 在 Service Mesh 中的工作机制
前几天 Gateway API 宣布在 0.8.0 中支持服务网格[1],这意味着 GAMMA[2](Gateway API for Mesh Management and Administration)有了新进展,虽然目前还是实验阶段。去年 6 月 Ga...【详细内容】
2023-09-08  Search: API  点击:(290)  评论:(0)  加入收藏
▌简易百科推荐
Meta如何将缓存一致性提高到99.99999999%
介绍缓存是一种强大的技术,广泛应用于计算机系统的各个方面,从硬件缓存到操作系统、网络浏览器,尤其是后端开发。对于Meta这样的公司来说,缓存尤为重要,因为它有助于减少延迟、扩...【详细内容】
2024-04-15    dbaplus社群  Tags:Meta   点击:(3)  评论:(0)  加入收藏
SELECT COUNT(*) 会造成全表扫描?回去等通知吧
前言SELECT COUNT(*)会不会导致全表扫描引起慢查询呢?SELECT COUNT(*) FROM SomeTable网上有一种说法,针对无 where_clause 的 COUNT(*),MySQL 是有优化的,优化器会选择成本最小...【详细内容】
2024-04-11  dbaplus社群    Tags:SELECT   点击:(3)  评论:(0)  加入收藏
10年架构师感悟:从问题出发,而非技术
这些感悟并非来自于具体的技术实现,而是关于我在架构设计和实施过程中所体会到的一些软性经验和领悟。我希望通过这些分享,能够激发大家对于架构设计和技术实践的思考,帮助大家...【详细内容】
2024-04-11  dbaplus社群    Tags:架构师   点击:(2)  评论:(0)  加入收藏
Netflix 是如何管理 2.38 亿会员的
作者 | Surabhi Diwan译者 | 明知山策划 | TinaNetflix 高级软件工程师 Surabhi Diwan 在 2023 年旧金山 QCon 大会上发表了题为管理 Netflix 的 2.38 亿会员 的演讲。她在...【详细内容】
2024-04-08    InfoQ  Tags:Netflix   点击:(5)  评论:(0)  加入收藏
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(9)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(16)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(14)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(9)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(15)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(10)  评论:(0)  加入收藏
站内最新
站内热门
站内头条