关于 React19,你需要了解的前因后果

大家好,我卡颂。

React当前的稳定版本是18.2,发布时间是22年6月,在此之后就没有新的稳定版本发布。

直到今年2月15日,官方博客才透露下一个稳定版本的计划。没错,他就是React19

为什么时隔1年多才公布下个稳定版本的计划?

为什么下个版本直接跳到了19?

18我都还没升呢,19就来了,是不是要学很多东西?

这篇文章会为你详细解答这些疑问。

打包领取卡颂原创React教程、加入人类高质量前端群

从React16聊起

近年来React最为人津津乐道的版本应该是16.8,这个版本引入了Hooks,为React(乃至整个前端框架领域)注入了新的活力。

再之后的v17没有新特性引入。既然没有新特性引入,为什么要发布一个大版本(从16到17)呢?

这是因为从同步更新 升级到并发更新React,中间存在breaking change

这么大体量的框架,在升级时需要保证过程尽可能平顺。这除了是一种专业、负责的体现,更重要的,版本割裂会造成大量用户损失(参考当年ng1升级到anuglar2时)。

当升级到18后,React团队发现 ------ 真正升级到18,并大量使用并发特性(比如useTransition)的开发者并不多。

更常见的场景是 ------ 知名开源库集成并发特性,开发者再直接用这些库。

所以,React团队转变策略,将迭代重心从赋能开发者 转变为赋能开源库。那么,什么样的库受众最多呢?显然是框架。

所以,React的重心逐渐变为 ------ 赋能上层框架,开发者通过使用上层框架间接使用React

为什么我说React团队转变了策略,而不是React团队一开始的计划就是赋能上层框架呢?

如果一开始的计划就是赋能上层框架React团队就不会花大量精力在版本的渐进升级上 ------ 反正开发者最终使用的会是上层框架(而不是React),版本割裂上层框架会解决,根本不需要引导开发者升级React

策略改变造成的影响

策略转变造成的影响是深远且广泛的,这也是为什么18.2后一年多都没有新的稳定版本出现。

最基本的影响是 ------ 特性的迭代流程变了。

React诞生的初衷是为了解决Meta内部复杂的前端应用,所以React之前的特性迭代流程是:

  1. 新特性开发完成

  2. 新特性在React内部产品试用,并最终达到稳定状态

  3. 开源供广大开发者使用

但随着策略转变为赋能上层框架 ,势必需要与主流上层框架团队(主要是Next.js)密切合作。

如果按照原来的迭代流程,上层框架团队属于Meta之外的第三方团队,只能等新特性开源后才能使用,这种合作模式显然太低效了。

于是,React团队提出了一个新的特性发布渠道 ------ canary,即:新特性开发完成后,可以先打一个canary版本的React供外部试用,等特性稳定后再考虑将其加入稳定版本中。

可能有些存在于canary中的特性永远不会出现在稳定版本的React中,但不妨碍一些开源库锁死canary版本的React,进而使用这些特性。

那么,为什么时隔1年多才公布下个稳定版本的计划?主要有4个原因。

原因1:新特性主要服务于Next,没必要出现在稳定版本中

策略改变除了影响特性的迭代流程 ,还让React团队成员陷入一个两难的境地 ------ 我该优先服务上层框架还是Meta

我们可以发现,在之前的迭代流程中,一切都围绕Meta自身需求展开。React团队成员作为Meta员工,这个迭代流程再自然不过。

但是,新的迭代流程需要密切与Next团队合作,那么问题来了 ------ 作为Meta员工,新特性应该优先考虑Next的需求还是Meta的需求?

为了完成赋能上层框架 的任务,显然应该更多考虑Next的需求。我们能看到一些React团队成员最终跳槽到Vercel,进入Next团队。

所以,在此期间产出的特性(比如server actionuseFormStatususeFormState)更多是服务于Next,而不是React

如果基于这些特性发布新的稳定版本,那不用Next的开发者用不到这些特性,用Next的开发者依赖的是canary React,所以此时升级稳定版本是没意义的。

原因2:新特性必须满足各种场景,交付难度大

Nextweb框架,围绕他创造的新React特性只用考虑web这一场景。

React自身的定位是宿主环境无关的UI库,还有大量开发者在非web的环境使用React(比如React Native),所以这些特性要出现在稳定版本的React中,必须保证他能适配所有环境。

举个例子,Server Actions这一特性,用于简化客户端与服务器数据发送的流程 ,当前主要应用于NextApp Router模式中。

比如下面代码中的MyForm组件,当表单提交后,serverAction函数的逻辑会在服务端执行,这样就能方便的进行IO操作(比如操作数据库):

js 复制代码
// 服务端代码

async function serverAction(event) {
  'use server'
  // 在这里处理服务端逻辑,比如数据库操作读写等
}

function MyForm() {
  return (
    <form action={serverAction}>
      <input name="query" />
      <button type="submit">Search</button>
    </form>
  );
}

App Router的场景主要是RSC(React Server Component),除了RSC外,SSR场景下是不是也有表单?不使用服务端相关功能,单纯使用React进行客户端渲染,是不是也有表单的场景?

所以,Server Actions特性后来改名为Actions,因为不止Server场景,其他场景也要支持Actions

比如下面代码中,在客户端渲染的场景使用Actions特性:

js 复制代码
// 前端代码

const search = async (event) => {
  event.preventDefault();
  const formData = new FormData(event.target);
  const query = formData.get('query');

  // 使用 fetch 或其他方式发送数据
  const response = await fetch('/search', /*省略*/);

  // ...处理响应
};

function MyForm() {
  return (
    <form action={search}>
      <input name="query" />
      <button type="submit">Search</button>
    </form>
  );
}

你以为这就完了?还早。form组件支持Actions,那开发者自定义的组件能不能支持Actions这种前、后端交互模式

比如下面的Calendar组件,之前通过onSelect事件响应交互:

html 复制代码
<Calendar onSelect={eventHandler}>

以后能不能用Actions的模式响应交互:

html 复制代码
<Calendar selectAction={action}>

如何将平平无奇的交互变成Actions交互呢?React团队给出的答案是 ------ 用useTransition包裹。所以,这后面又涉及到useTransition功能的修改。

Actions只是一个例子,可以发现,虽然新特性是以web为始,但为了出现在稳定版本中,需要以覆盖全场景为终,自然提高了交付难度。

原因3:老特性需要兼容的场景越来越多,工作量很大

新特性越来越多,老特性为了兼容这些新特性也必须作出修改,这需要大量的时间开发、测试。

举两个例子,Suspense在v16.6就引入了,它允许组件"等待"某些内容变得可用,并在此期间显示一个加载指示器(或其他后备内容)

Suspense最初只支持懒加载组件(React.lazy)这一场景。随着React新特性不断涌现,Suspense又相继兼容了如下场景:

  • Actions提交后的等待场景

  • 并发更新的等待场景

  • Selective Hydration的加载场景

  • RSC流式传输的等待场景

  • 任何data fetching场景

为了兼容这些场景,Suspense的代码量已经非常恐怖了,但开发者对此是无感知的。

再举个和SuspenseuseEffect这两个特性相关的例子。

Suspense为什么能在中间状态完成状态 之间切换?是因为在Suspense的源码中,他的内部存在一个Offscreen组件,用于完成两颗子Fiber树的切换。

React团队希望将Offscreen组件抽离成一个单独的新特性(新名字叫Activity组件),起到类似VueKeep-Alive组件的作用。

Activity组件既然能让组件显/隐,那势必会影响组件的useEffect的触发时机。毕竟,如果一个组件隐藏了,但他的useEffect create函数触发了,会是一件很奇怪的事情。

所以,为了落地Activity组件,useEffect的触发逻辑又会变得更复杂。

原因4:特性必须形成体系才能交付

虽然这一年React团队开发了很多特性,但很多特性无法单独交付,必须构成一个体系后再统一交付。

比如刚才提到的useFormStatususeFormState是服务于Actions特性的,Actions又是由Server Actions演化而来的,Server Actions又是RSC(React服务端组件)体系下的特性。

单独将useFormStatus发布在稳定版本中是没意义的,他属于RSC体系下的一环。

所以,即使新特性已经准备就绪,他所在的体系还没准备好的话,那体系下的所有特性都不能在稳定版本中交付。

总结

为什么时隔1年多才公布下个稳定版本的计划?主要是4个原因:

  1. 新特性主要服务于Next,没必要出现在稳定版本中

  2. 新特性必须满足各种场景,交付难度大

  3. 老特性需要兼容的场景越来越多,工作量很大

  4. 特性必须形成体系才能交付

那为什么下个稳定版本不是v18.x而是v19呢?这是因为部分新特性(主要是Asset LoadingDocument Metadata这两类特性)对于一些应用会产生breaking change,所以需要发一个大版本。

从上述4个原因中的第四点可以知道,既然有v19的消息,势必是因为已经有成体系的新特性可以交付,那是不是意味着要学很多东西呢?

这一点倒不用担心,如果你不用Next,那你大概率不会接触到RSC,既然不会接触RSC,那么RSC体系下的新特性你都不会用到。

v19对你最大的影响可能就是新特性对老API的影响了,比如:

  • useContext变为use(promise)

  • Activity组件使useEffect的触发时机更复杂(应该不会在v19的第一个版本中)

这些的学习成本都不大。

关于v19的进一步消息,会在今年5月15~16的React Conf公布。

相关推荐
bysking19 分钟前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
独行soc26 分钟前
#渗透测试#SRC漏洞挖掘#深入挖掘XSS漏洞02之测试流程
web安全·面试·渗透测试·xss·漏洞挖掘·1024程序员节
王哲晓35 分钟前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_41138 分钟前
无网络安装ionic和运行
前端·npm
理想不理想v40 分钟前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云1 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205871 小时前
web端手机录音
前端
齐 飞1 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
神仙别闹1 小时前
基于tensorflow和flask的本地图片库web图片搜索引擎
前端·flask·tensorflow
sszmvb12342 小时前
测试开发 | 电商业务性能测试: Jmeter 参数化功能实现注册登录的数据驱动
jmeter·面试·职场和发展