那些在业内待得足够久的人,都见过这句话的各种版本的兴衰:
没有人因为选择了IBM而被解雇过
Google上的第一条结果有一篇很棒的博客文章讨论了这一点:
这是一句没有明确来源的引言,在科技圈中被反复引用,以至于深植于许多长期使用IBM®用户的思维中。
这对进步来说是一个问题。
这是一种墨守成规的心态——纯粹创新的最大敌人。
引用保罗·莱施钦格(Paul Liesching)撰写的一篇非常出色的领英文章:
当然,这句话的真实含义是没有人因为购买现有大型品牌而被解雇。
在80年代,这种理念被销售理念“FUD”(恐惧、不确定性和怀疑)巧妙地利用了。恐惧、不确定性和怀疑一直是大型品牌销售和营销武器库中最致命的工具,至今仍然如此。
大型组织中CIO(首席信息官)的最大目标是“不要失败”,或者如果失败了,确保不是他们的责任。购买安全的现有大型品牌一直完美地支持了这一目标,直到现在。
这种情况变换了多次;将“IBM”替换为“Oracle”、“Microsoft”、“Intel”或“SAP”,你就能明白这一点。
虽然React显然不是一个公司,但我认为React现在戴上了同样的王冠:它成为了阻碍进步的障碍,并且是守旧思维的象征。
前端现状2022年The State of JS调查不出所料地显示,React在使用量上仍然位居第一。事实上,它在市场份额上继续增长(至少在此次调查的有限受众中):
React的实际使用量实际上在增加;据我看来,这可能与Next.js的增长有关。
如果我们用YCombinator的工作于初创公司的招聘网站作为初创公司世界的参考,你会发现它更倾向于React:
一个很好的代表整个创业领域的东西。
它甚至已经被像Target这样的大型企业使用:
Target的官网使用了Next.js
以及沃尔玛:
沃尔玛的在线商城使用了Next.js
即使微软团队——那个每个人都爱恨交加的协作工具——现在也在用React重写:
这已经是非常企业级的了!
没有任何信号比这更清楚地表明,React 现在是“安全”的、_企业级_选择——现代的 IBM —— 而这可能就是你为什么不应该选择它。
React 存在的问题 性能在主要的前端库——React、Angular、Vue、Svelte和Preact中,React是表现最差的库之一。
无论是就负载大小而言:
via Tim Kadlec
或者 CPU 时间:
via Tim Kadlec
React 表现得很糟糕。
执行时长
在几乎所有重要的性能方面:
内存分配
React 的糟糕载荷大小、执行速度慢以及高内存消耗使其成为面向移动用户群体的 web 应用程序的较差选择。
这种情况在开发者使用高速互联网连接和现代设备时往往会被忽略,尤其是在企业环境中,硬件和网络连接更加统一。但在消费者领域呢?在发展中国家呢?在旧设备上呢?最终用户会遭受这种性能损失。
生态系统 vs 创新尽管如此,React 仍然是前端开发中使用最广泛的库。
这其中一部分原因是,它类似于IBM或微软鼎盛时期自证预言的副产品:选择IBM、微软或Oracle或React的生态系统和所谓的“安全性”形成了一种自我强化的循环,我看到这种现象被表达为:
while (react.isPopular) {
react.isPopular = true
}
但这造成了一个盲点:创新。
你看:生态系统越大 → 依赖关系越多 → 企业支持力度越大 → 创新的难度越高。不仅仅是为了创新本身,而是为了提升性能、改善开发体验(DX)、改善用户与现代 web 应用互动的体验。一旦某个阵营获得了 React 这样的市场主导地位,创新几乎注定会被搁置。一方面:是因为对稳定性的期望更高。另一方面:这使项目领导团队滋生出一种封闭且自大的心态。
难道还有比这更维持现状的吗?
当我第一次看到安德鲁·克拉克的推特时,我认为这是一条玩笑。肯定是在开玩笑吧?克拉克承认,使用信号实现的细粒度反应性是“非常适合性能的”…
“但我更喜欢React的模型,即每次都假装整个东西都被重新创建”
这可不是开玩笑的;事实上,尽管所有证据都表明有更好的、更快的模型,React 团队还是会坚持这种做法。这是因为团队首先受限于其市场份额,同时也太傲慢,不肯承认他们一直在向我们——开发者和最终用户——推销劣质产品。
正如 Alex Russell 在他的评论文章中写道:
柠檬市场依赖于顾客比销售劣质产品的商家拥有更少的信息。早期炒作这些技术栈的一些人是出于真诚的无知,这种无知在认识到错误并导致行为改变时是可以原谅的。但这并不是过去十年中最受欢迎的框架所做的事情。
安德鲁·克拉克提出的通过使用更多编译器魔法来解决React的不足,确实是一种非常像Facebook的解决问题的方法,这种方法侧重于通过提高性能和适应底层技术模型来解决问题。我们已经看到了Facebook的Hiphop虚拟机——用于解决PHP在大规模应用中的问题——以及Hack编程语言的类似做法。
一方面,我认为我们应该赞扬React团队,因为他们确保了那些已经在React上投入的团队不必从头开始(就像他们能够通过HipHop来优化性能不佳的PHP一样)。然而,另一方面,你可以看到React的解决方案是进一步偏离了构建Web UI的渐进式方法,通过将更多的“魔法”强制放入编译器中来使一个已经失败的模型继续运行。
对我来说很清楚,React 是一个死胡同,它根本性的缺陷只能通过编译器魔法来解决。我们在这里构建的是 JavaScript 和 HTML 前端,而不是操作系统!
或许更重要的是,那种编译器魔法解决的是错误的问题。
复杂度就像旧时代的IBM大型机系统和微软的企业软件如SharePoint一样,这类系统的复杂性是被严重低估了。这就是占据主导地位并成为“安全”选择的一部分力量:市场份额创造了一种错觉,当真正面对问题时,这种错觉带来了大量的恐慌、不确定和怀疑(“如果我们找不到任何JavaScript/Svelte/Vue/Solid/Preact开发者怎么办?!”)。
又一次,Alex Russell 的文章直截了当地指出:
这些复杂度商人知道他们的环境并不典型,但他们却将高度专业化的工具当作适用于一般情况的工具来销售。他们明白大多数网站缺乏严格的延迟预算、专门的性能团队、严格的管理层审查、防止退化的发布门禁以及对关键用户旅程的端到端测量。他们明白,要扩展由JavaScript驱动的前端,唯一的办法是进行大规模的投资来控制复杂性,但他们从未向客户提及这一点。
他们本可以坦诚地承认这是一个诚实的错误,承认这些技术需要庞大的基础设施才能运行;在大多数团队手中,这些技术是无法扩展的。但他们却反其道而行之,加倍努力,年复一年地宣布虚无缥缈的新功能,以避免对根本性设计缺陷进行批判性思考。他们还暗中打压那些指出令人不安的结果和高昂成本的人。
React 的复杂性虽然隐藏得很好,但其本质在于渲染周期假设组件是无状态的,这意味着开发者需要理解何时以及何地谨慎地放置状态。
React 的准函数模型对管理状态的难度做了一些假设,我认为这些假设并不成立。World of BS 对不同的编程哲学及其对状态的看法有一个简洁明了的介绍:
我最近意识到,各种编程哲学都与状态有关,可以归结为一个关于如何处理状态的简单陈述。
面向对象 — 一次性修改大量状态很难正确处理;将状态的子集封装到不同的对象中,并通过方法允许有限地操作封装的状态。
函数式 — 修改状态很难正确处理;将状态保持在边界处,并保持逻辑的纯粹性,以便更容易验证逻辑的正确性。
这样来看,你就能理解为什么React的Hooks模型在与它的函数式目标相一致时会如此令人困惑:Hooks在概念上更像是一种带有getter
和setter
的对象封装状态(感谢Amy Blankenship提出这个想法)。
我同意Evan的观点;在我看来,JavaScript的这种混合特性也是它的魅力和力量的一部分。React希望我们在一种语言模型中强行套用一种范式,在这种模型中,由于语言本身不纯且不完美,无法支持不可变的功能范式,因此必然会存在一些漏洞。
这种关于编程哲学及其看待状态的观点似乎非常准确。有趣的问题是,网页UI是否更偏向于状态还是逻辑,从而考虑哪种模型更适合。接下来的问题是:React的功能化方法是否真的降低了正确处理逻辑和状态的复杂性?(如果你参与过任何足够大型的React项目,你已经知道答案了。)
如果你发现自己在发现了一个意外的副作用后回到代码中,添加了 useMemo
和 useCallback
以解决UI中的奇怪错误,或者反过来,移除了过度使用的 useMemo
和 useCallback
,那么欢迎加入我们的行列。React 的渲染模型和对函数纯度的坚持在考虑到每个有状态的UI应用程序库或框架(无论是桌面应用、移动应用、3D游戏库等)的设计时,是反直觉的。
是的,在底层,显卡会逐帧绘制并丢弃之前的像素渲染缓冲区,但这只是硬件层面的实现细节。抽象层的存在意味着这些低级细节不会影响到开发者,我们通常总是假设我们的UI组件或对象是有状态的。换句话说,像Unreal、Unity或Godot这样的引擎通过在无状态帧渲染管道之上添加有状态的抽象来提高开发效率。
或许Facebook要求React开发者假装每次都在重建DOM树(但实际上并没有重建)是有原因的🤷♂️。
这让我想到了我的下一个观点:
它并不能解决_你的_问题毫无疑问:React 的初始学习曲线非常低,因为 React 本身主要关注简单的渲染和最基本的状态管理。即使你不太擅长使用 React(例如,编写带有副作用的非“纯”组件),在小型项目中你也很少会注意到这些问题。
然而,React 通过状态变化重新创建整个 UI 的逻辑模型在大规模应用中 是非常难以做好的。我的意思是,随着应用程序和团队的扩大,随着上下文提供者的层次增多,由于技能、知识、经验的差异,以及代码量的增加,编写具有意外副作用的组件的可能性也随之增加。
对于Facebook以及大型企业团队如Target、Walmart和Microsoft来说,这可能通过严格的测试、额外的工具和更好的培训来管理。那么问题来了,对于希望快速发展的初创公司或小型团队而言,React是否是最好的工具?我认为答案是否定的;React是为了解决Facebook在Facebook的规模和资源下的问题而诞生的。
在某种意义上,这让人想起了Scott Carey的文章《复杂性正在扼杀软件开发者》,其中有一句精彩的引言:
“关键在于你所从事的业务领域的复杂性,企业本身就是极其复杂的环境,因此他们试图解决的问题本质上是复杂的。另一个方面是偶然的复杂性;这是由于我们的工具和在解决问题时叠加的层面上带来的复杂性。”
特别是,Carey 指出从单体架构转向微服务是现代架构中复杂性的一个关键来源。
我最喜欢的微服务实现方式。
当然,微服务及其带来的额外复杂性在某些时候和场合是有其位置的,但每个团队都需要问自己一个问题:“我真的需要这个吗?现在吗?”还是这只是“复杂性商人”试图推销他们的产品。
前GitHub首席技术官Jason Warner对微服务的看法。
就像 React 的复杂性一样,答案可能是“不”;我们大多数人 没有 用 Facebook、Target 或 Walmart 的资源和解决他们规模问题的选项,也没有使用 Facebook、Target 或 Walmart 级别的 hack 和 workaround 的选择。
对于其他人来说——尤其是初创公司——能够快速行动而不自乱阵脚可能是选择技术栈更重要的方面。
在React生态系统周边,许多有用的创新正在UI领域发生:Solid.js,Preact.js,Svelte.js,Vue.js,Astro.js,HTMX(为什么要对整个页面进行SSR,当你只需对发生变化的部分进行SSR即可呢?),Qwik.js,Marko.js,Deno Fresh,以及使用现代JavaScript功能进行的渐进式增强。
Vue 3.4的[defineModel](https://medium.com/p/9390c8e68aa5)
宏 是一个很好的例子,说明即使是看似微小的创新也能对开发体验(DX)和迭代速度产生深远的影响。
就像IBM一样,React终将有一天会因为自身的庞大和无法创新出更好的解决方案而失去其地位。这一点已经体现在团队如何看待前端现状以及如何继续(不)改善开发者、团队和最终用户体验的方式上。与Vue的创始人Evan You不同,他没有问题地从其他团队借取更好的想法(例如Vue即将推出的Vapor模式),React团队却只是在承认有更好的模型可以提高性能的情况下仍然坚持自己的做法;当手中只有柠檬时,很难停止销售柠檬!
React 就像新的 IBM:你应该学习它,理解它的缺点,可能你仍然应该在正确的上下文中部署它。选择它不会让你被解雇,但它的使用会很昂贵,臃肿,难以正确使用,并且每一步的实现都会让人感到乏味。React 确实是“现状思维——纯粹创新的最大敌人”。
共同学习,写下你的评论
评论加载中...
作者其他优质文章