(转译) Bun 炒作:我们从 Yarn 中学到了什么

最近被迫需要摸一下 yarn 和 bun 的项目,在作对比的过程中发现了一篇很有意思的观点文章,通读之后感觉蛮有意思,因此让克劳德翻译了一下全文贴在这里;原作者是 The Jared Wilcurt,原文地址在 dev.io 上,如果有兴趣建议阅读原文。
译文如下
Bun 炒作:我们从 Yarn 中学到了什么
bunjs | javascript | node | npm
历史再次重演,我们正在犯同样的错误。我经常被提醒,每5年全球程序员数量就会翻一番,这意味着在任何时候,行业中50%的人员经验不足5年。这可能就是为什么我们不断被 Bun 这类东西所吸引的原因。但我曾经见过这种情况,我知道结局如何。
第一部分 - Yarn 的故事
我看到 Yarn 和 Bun 之间有很多相似之处。两者都针对现有的开源系统,但不是实际贡献,而是创建了自己的竞争技术。两者都以速度更快为卖点。两者都以分裂生态系统为目标。两者都没有良好的向后兼容支持。两者都宣布他们已经正式发布 v1.0 并可用于生产环境!...但实际上却不支持 Windows(也就是说:实际上根本就不能称为生产就绪)。
那么 Yarn 后来怎么样了?它推出了十几个 npm 没有的新功能。它的速度比 npm 快了好几倍。但是...仅仅一年后,npm 已经比 Yarn 更快了。又一年后,Yarn 发布了一篇博客文章,解释了为什么他们最终不可能比 npm 更快,因为 npm CLI 是由负责存储和下载包的 npm 服务器的同一批人创建的。时至今日,这一点仍然成立。在2023年,npm 仍然比 Yarn 更快。它最初的主要卖点...在5年内都不再相关。
但是 Yarn 提供的其他功能呢?随着时间的推移,越来越多的功能被实现并在 npm 中发布,截至今天,Yarn 曾经提供的所有独特功能都已内置到 npm 中。当然,这些功能的实现方式略有不同,对于那些真正关心 Yarn、Lerna、Turbo 和 npm 处理单仓库管理的细微差别的人来说,可能更喜欢其中一个。但对于绝大多数用例来说,npm 实现这些功能的方式对几乎所有用户来说都足够好。
啊,但是 Bun 肯定不同,对吧?毕竟,它是用 ZIG 编写的!而 ZIG 超级快...对吧?呃,不完全是。它没有做任何魔法般的事情,最终您可以用 ZIG 实现的任何性能也可以用 C++(Node.js 的编写语言)实现。所以,就像旧的缓慢的 npm 的故事一样,一旦性能被优先考虑,npm 就能达到与竞争对手相同(甚至更快)的速度。我可以看到 Node 也会发生类似的情况。如果给予适当的关注,应该可以达到大致相当的速度,直到差异变得可以忽略不计。好吧...某种程度上。我们应该承认,Bun 吹嘘的一些基准测试是精心挑选或具有误导性的。所以,即使 Bun 也不能达到它自己营销炒作的水平。但您明白我的意思。
回到 Yarn 的寓言。当 Yarn 出现时,它声称支持 Windows。但是没有一个为 Yarn 工作的 Facebook 开发人员将 Windows 作为他们的主要操作系统。所以他们很快发现,Yarn 实际上在发布时不能在该平台上运行。
简短的题外话:你好,Primagen(其他人可以跳过这段)。我知道,你已经对 Windows 做了一个刻薄的评论。但也许你应该尝试真正重视我们社会中的多样性,接受不同的生活方式。我的意思是,我理解。我完全理解,Windows 用户只占计算机用户的一个非常非常小的少数,仅90%。但也许...我们应该尊重这个几乎不引人注意的少数群体。:)
回到故事。
所以大约两周后,他们终于"修复"了它,Yarn 可以在 Windows 上安装和运行了...勉强可以。实际上,直到他们转向使用 corepack,我才能在 Windows 上可靠地运行 Yarn。一旦您可以通过 npm 安装 corepack,然后在上面安装 Yarn(或 pnpm),它终于以可靠、无错误、不崩溃的方式与 Windows 兼容了。但到那时,Facebook 已经放弃了 Yarn,慢慢地,其他人也放弃了,当它开始在 Windows 上运行时,它已经开始衰落了。
直到今天,我仍然无法在 Windows 上运行 Yarn 单仓库。我确信这是不可能的。任何声称他们成功运行的人都在骗你。当然,也许在某些没有安装任何东西(甚至没有 Windows 更新)的 Windows 虚拟机中,也许有人让 Yarn 单仓库在 Windows 上运行了几秒钟。也许他们还在森林里看到了大脚怪。任何事情都可能发生。但在真正的开发人员笔记本电脑上,PATH 中有随机内容,安装了 Node 和 nvm-windows 和 volta 以及谁知道还有什么其他随机东西,不,它不工作。
好吧,所以 Yarn 出现了,迫使 npm 变得更好,然后消亡了。有什么问题呢?如果这就是它所做的一切,那么 Yarn 会很棒,但可悲的是事实并非如此。npm 专注于开发和发布绝大多数用户需要的功能。但 Yarn 专注于 Facebook 需要的功能。其中许多对99%使用 npm 的人来说并不重要。然而,一旦人们开始使用 Yarn,npm 不得不重新优先考虑他们要开发和发布的功能。与其提供对更多用户更相关的更高价值功能,他们不得不迅速追赶并添加与 Yarn 提供的功能相当的功能,以避免生态系统分裂。但 Yarn 营销得很好,人们买账了。当它出现时,即使是我也对 Yarn 充满期待,直到我发现它实际上不能在 Windows 上运行。但其他人没有意识到这一点,或者不关心这一点,并采用了它...然后...然后...
...然后 Yarn 变成了部落化。愚蠢的人类。一切都必须变成部落化。几年来,有成千上万的 README 文件创建在项目上,它们只告诉你 Yarn 安装项目的指令。这让新开发人员感到困惑。我无法告诉你有多少初级开发人员来找我,询问这个"Yarn 东西"是什么,以及他们是否需要它。以为他们发现的项目只能与 Yarn 一起工作。这浪费了所有人的时间和精力。
我一直认为 Facebook 的某个人发现,说服他们的老板让他们花时间为他们不能获得荣誉的开源项目添加功能是一个很难的卖点。如果他们可以将其用于招聘营销或类似目的,那么获得批准从事这些功能的工作可能更容易。它总是散发着"不是在这里发明的"综合症的气味。
如果 Facebook 只是为 npm 贡献他们想要的功能,那么他们的功能就会与 npm 已经在开发的功能一起发布。但相反,它延迟了这些其他功能的发布多年,导致重复工作。而这一切是为了什么?Yarn 基本上已经死了,除了少数特殊情况。但在过去一两年里,我没有在 README 中看到 yarn add。这是过去时代的标志。
第二部分 - Bun 实际上更糟糕
与 Yarn 不同,Yarn 提供速度和十几个新功能,Bun 提供速度和大约3个新功能。让我们简要地回顾一下它们。
宏(Macros)- 在构建过程中使用。有些人称其为错误。我最大的担忧是,您的构建过程现在被 Bun 卡住了。除非其他工具有等效的宏系统,否则您无法切换到其他工具,或者您需要重写构建过程。您正在选择未来的技术债务。
bun.x APIs - 这些是新的 API,它们字面上做与 Node.js API 相同的事情,但"更快"。这比宏更糟糕,因为现在您的代码是 Bun 病毒。如果我 npm install 您的包并在 Node 中运行它,当尝试使用您的库时,我会得到 ReferenceError: Bun is not defined。迫使您库的所有用户采用 Bun。这是对生态系统的另一次强制分裂,类似于 Yarn 所做的,但更糟糕。
我也许可以看到一些包装库,您导入它,检查 bun 是否存在,如果存在则使用更快的 API,如果不存在则回退到 Node。如果 Bun 变得稍微流行,我想这将非常普遍。但这只是您项目中需要维护的另一个依赖项,这在某种程度上违背了"一体化"系统的目的,如果使用它的每个人都必须安装额外的工具库来使其更易于使用,那么您可以跳过拥有工具依赖项。
元语言支持 - Node.js 应该内置 Vue-Template-Compiler 吗?问这个问题听起来绝对疯狂。Markdown、Sass 或 CoffeeScript 呢?是的,让所有东西都建立在上面的主平台内置这些将是非常愚蠢的。这会让人感觉非常短视。
元语言的存在是为了填补原始语言中的空白,它们本质上是非永久性和灵活的。它们就像在您驾驶经过原始语言中的坑洼时为您的车添加非常好的悬挂系统。直到原始语言能够填补这些坑洼。我们不再使用 CoffeeScript 是有原因的,它提供的大多数功能都在 ES6 中被添加到语言中。CSS 已经慢慢添加了一些"足够好"的等效功能来对应 Sass 的高价值功能,之后我们看到 Sass 使用量首次下降。但是我们现在有了最糟糕的模板系统 JSX 和最有争议的前端工具 TypeScript 内置到 Bun 中。
TypeScript 的使用在2020年左右达到平稳期(JS 生态系统中有三分之一多一点采用了它),在过去一年中,随着更好、更简单的替代方案如 eslint-plugin-jsdocs(从这里开始)和潜在的基于注释的 ES202X 官方类型系统取代它,它终于显示出第一个衰退迹象,这可能导致创建 .ts 文件的需求迅速下降。随着这些坑洼被填补,TypeScript 将需要寻找新的坑洼来尝试平滑并证明其存在的必要性,或者接受它的工作已经完成并慢慢消失。就像所有其他我们已经超越其实用性的曾经有用的技术一样(LESS、Stylus、Sass、CoffeeScript、Yarn、Grunt 等),它永远不会真正消亡。
Sass 是一个很好的例子。在某个时候,约96%的前端开发者使用它,满意度超过90%(2019年CSS状态)。但随着元语言的API演变为变得更加复杂以解决更复杂的问题,它的使用和满意度都下降了。它不再专注于成为适合所有人的简单工具,而是专注于成为适合做非常高级事情的人的非常高级工具。一个更加小众的用途。
我一直在想,如果 Bun 在前几年出现,它会由什么奇怪的技术混合体组成,今天它们会被困在维护什么样的遗留代码。如果它在2019年 Sass 的巅峰时期出现,基本上每个人都在使用它,将其内置到 Bun 中完全有意义,对吧?但是当所有 Sass API 更改并且旧的导入系统完全被弃用时,你会怎么做?通常,您只需为项目 npm install 您需要的 Sass 版本,如果这是您的代码工作的版本并且您不想升级,则固定旧版本。但是如果您为此使用 Bun,然后几年后回来,现在项目就无法构建了,因为 Bun 中的 Sass 版本与您编写的 Sass 代码不兼容,您需要花一天时间尝试弄清楚您的代码实际需要什么版本,并手动安装正确版本的 Sass 以使您的项目再次运行。这就是为什么将元语言内置到 Node.js 或扩展的 Bun 中是疯狂的原因。但这是他们所做的,我预见未来对那些严重依赖它而不是简单快速方便的人会有痛苦。
最后一个,内置的元语言,有点倾向于 Bun 真正是什么。它只是一堆技术的抽象层。它不是一个真正的替代品或竞争对手,它实际上是完全相同的东西,只是已经内置了。这在纸面上听起来不错,但最终相当糟糕。
抽象可以很好,并简化事情。让我们以 Webpack 为例。Webpack 是...嗯,就是可怕的。没有人喜欢处理它。这就是为什么每个 JS 框架都必须为它构建一个抽象层,因为没有人想接触 Webpack。像 Angular-CLI、Create-React-App、Svelte-CLI 或出色的 Vue-CLI(甚至有一个 GUI)。我们以 Vue 为例,因为它在所有这些抽象中做得最好。vue.config.js 文件是一个简单的配置,它抽象了 Webpack 的所有复杂性,同时如果需要,仍然给您相同级别的控制。它还将依赖项数量从大约30个减少到大约3个。但后来 Vue 的创建者 Evan You 制作了 Vite。vite.config.js 基本上与 vue.config.js 具有相同级别的复杂性,只是不需要他们维护一个完全独立的项目(Vue-CLI)来使其变得这样。从 Vue-CLI 切换到 Vite,我最终拥有相同数量的依赖项和相同数量的配置代码。最终结果是 Vite 是 ESBuild 的抽象层,使用起来与它所替代的最佳抽象层一样简单。
但 Bun 没有这样做。它不是将困难的事情变成更简单的抽象。它接受 ESBuild 并像 Vite 一样抽象它。这不是一个改进,它基本上是相同的东西。对于单元测试也是这种情况。他们甚至不假装提供新东西,而是告诉您像正常的 Jest 或 Vitest 那样编写代码,他们只会劫持导入并在幕后用自己更快的代码替换它们。
Bun 只是我们已经拥有的工具之上的抽象层。这意味着它将始终落后于曲线,并可能在该层引入额外的错误。对于安装依赖项、测试代码和构建要发送到生产的代码等关键系统来说,这不是理想的。
但我们甚至还没有讨论 Bun 做的最糟糕的两件事,以及真正可怕的部分。
Windows
我挑剔 Yarn 对 Windows 的糟糕支持。但与 Bun 相比,它们看起来很棒。至少当他们发布它时,他们有某种程度的 Windows 支持。它只是偶尔勉强工作,但它存在。然而,在 Bun 吹嘘的几十个功能中,当它作为"版本1.0"发布时,甚至没有一个在 Windows 上受支持。
"Windows 构建是高度实验性的,不适合生产环境。只启用了 JavaScript 运行时;包管理器、测试运行器和打包器已被禁用。性能未优化。" - 官方 Bun 1.0 博客文章
所以想象一下,他们刚刚发布并展示了所有这些他们感到兴奋并希望人们使用的酷功能。更可能发生的是什么?随着成千上万的人开始使用它并提供反馈、发现错误、请求功能、需要支持,您认为他们会:
A. 在接下来的一年中完全忽略所有新用户,专注于实现完整的功能对等性并制作一个经过打磨的、坚固的、可靠的、超快的、与 Windows 兼容的构建。可能会扼杀他们从初始炒作周期中建立的任何动力,甚至可能失去他们一直依赖的风险投资资金。
B. 将他们非常小的团队的几乎所有精力集中在保持现有用户满意上,通过改进已经基本工作的 Linux/OSX 版本,使产品看起来维护良好并可以在这些社区中慢慢获得采用,同时被部落开发者病毒式传播,他们故意创建不可移植的代码,知道它在 Node 中甚至在 Windows 上都不会工作。
我真诚地相信他们有意在 Windows 上构建和运行版本。我只是一秒钟都不相信在1.0版本发布一年后,他们将在 Windows 版本中实现功能对等。也许到那时 Windows 版本将与版本1.0具有功能对等性,但我怀疑他们会停止一年的 Linux 版本的所有工作。在那一点上,两种 Bun 口味将彼此不同步,导致混乱。
这让我们进入 Bun 最大的缺失功能。
没有 Bun 版本管理器
在他们放入 Bun 的所有工具中,他们没有内置的一个工具是版本管理器。对我来说,这是疯狂的。我认为 Node.js 没有内置版本管理器实际上也是疯狂的。让我们分解一下。在 Node.js 上,我有:
- nvm - 在 linux/osx 上基本上工作正常,但有一些烦恼。
- nodist - 很棒,但只适用于较旧版本的 Windows。
- nvm-windows - 适用于较新的 Windows 版本,但几乎无法工作并且充满错误。
- volta - 具有所有版本中最糟糕的 API,但也是最稳定和可靠的,可在所有操作系统上运行,甚至是非常旧的 Windows 版本。
为什么我必须了解这4个工具?这很愚蠢。但比必须处理4个做同样事情的工具更糟糕的是根本没有任何工具。
Node.js 比 Bun 更专注于向后兼容性。但随着时间的推移,即使是 Node 也废弃了它们 API 的部分内容。很多时候,这是 V8 引擎本身废弃功能的结果。Node.js 实际上在某种程度上参与了 V8 的方向,即使有一定程度的输入,他们也不可能避免所有的破坏性变更和废弃,导致旧的 Node.js 代码在较新版本的 Node 上根本无法工作。
所以我一秒钟都不相信 Bun 在第一次尝试时就把所有事情都做对了,并且它的任何部分都不会随着时间而改变,以及您在其中编写的所有代码将永远工作。特别是因为他们继承了将会出现在他们使用的 Apple Webkit JS 引擎中的任何废弃。
一年后当 Linux 上的 Bun 1.8 出来,但 Windows 刚刚达到1.0会怎样。在我工作的地方,我团队中的开发人员使用不同的操作系统(Linux、OSX、Windows)。如果我们不能自由地在 bun 版本之间切换,那么我们的 Linux 用户将无法降级到版本1.0,这样我们就可以使用相同的功能(慷慨地假设到那时会发布 Windows 版本)。
我们作为 Web 开发人员使用 Grunt 进行构建工具。然后 Gulp 出现并简化了这个过程,我们转向了它。然后 Gulp 4 出现并完全改变了 API,没有人想处理这个问题,所以我们转向 npm 脚本进行基本的构建自动化。但后来我们想要实际的打包能力和树摇动。所以,作为整个 JS 社区,我们转向了 Webpack(或更准确地说,它之上的抽象)。但 Webpack 很慢且烦人,所以当 Vite 出现时,我们都转向了它。
但是你知道吗?我并不热爱 Vite。现在它是最好的吗?是的,它是。但有些地方我希望更好。随着时间的推移,将会确定越来越多的这些问题,有人会不可避免地制作一个比 Vite 更好的新工具,我将愉快地转向它。不是因为我喜欢改变工具,而是因为从实用的角度来看,它会更好,我会看到其中的价值并转向它。就是这样。
即使您认为"不,我们的工具没有什么可做的了,我们已经完善了压缩"。您认为我们已经完善了网络上的一切吗?今天存在的网络功能在10年前不存在的是什么?假设10年后,我们终于在浏览器中有了一些替换 Web 组件且不糟糕的东西?我们难道不需要某种形式的新构建工具来转换我们的代码并利用这些原生功能吗?就像我们今天所做的那样?随着网络和互联网协议的变化和改进,我们如何为它们优化我们的包也会改变。网络一直在变化和进化。它从未停止。它将继续变化,我们的工具将继续对这些变化做出反应。
Bun 正在抽象的一切也将如此。它什么时候决定放弃其 ESBuild 抽象并切换到那个新东西?如果它切换得太早,而社区转向其他东西,它需要再次切换怎么办?你只能做这么多来保护你的终端用户免受 API 变更的影响。如果所有 Bun 用户都需要维护一堆 ESBuild 插件来与 Bun 一起工作,然后 ESBuild 从底层移除并替换,那么这些用户就会被困在旧的 Bun 版本上。
当您使用 Bun 来处理您的构建和您的核心 JS 运行时和您的测试工具时会发生什么。然后 Bun 对这些系统之一进行重大破坏性更改,需要大量技术债务来更新您的代码库以能够切换过去。也许您的所有测试都需要升级才能与新系统一起工作(我在工作代码库中进行了3次重大测试重构,最长的一次花了约6个月才完成,这种事情会发生)。升级所有代码可能需要数月,甚至整整一年。在此期间,您被困在旧版本的 Bun 上,直到所有内容都与新版本一起工作。但是,哦不!在 JS 运行时中发现了一个重大安全问题。所以您需要更新 JS 运行时,但您不能这样做,因为您的 JS 运行时和您的构建工具和您的测试工具都是相同的。在您的重大测试重构完成之前,您的代码是有漏洞的。在某些行业,您需要在一定时间窗口内解决安全问题。对这些人来说,Bun 是不可行的。
他们有办法处理这个问题,比如提供多个构建工具或测试工具,让您通过 CLI 参数切换到新的或旧的。但他们支持多个内置的替代工具多长时间?他们能负担得起支持所有这些吗?
随着他们内置到 Bun 中的所有各种工具抽象,只是时间问题,将所有这些粘合在一起的东西将变得太难以管理。Node、npm、Jest、Vite 等。这些都是每个工具单独解决的大型且非常复杂的问题空间。甚至 Vitest,在底层与 Jest 共享约80%的代码,仅尝试处理另外20%就是一项重大努力。
当 JavaScript Shadow Realms 发布时会发生什么?Vitest 已经计划采用 Shadow Realms 作为隔离 JavaScript 测试而不必启动新 Node 进程的方法。如果我的 Vitest 代码依赖于在这种隔离模式下运行,而 Bun 决定劫持我的导入而不是使用实际的 Vitest 导入,突然我的测试可能会开始随机失败,除非从等式中移除 Bun,否则我无法做任何事情,直到他们可以更新他们底层的代码以使用 Shadow Realms。但如果 realm 被添加到 V8 中,但是 Apple 拖延几年在 Safari 中添加支持(他们经常这样做)怎么办?在这种情况下,Bun 除了制作自己的内部原生 shadow realm 实现直到该功能内置到 Webkit 中外,别无选择。这将是一项相当大的工作,而且对于可能出现的其他类似问题来说,从长期来看不是一个非常可扩展的解决方案。
所有这些原因以及更多,就是为什么 Bun 版本管理如此重要。以及为什么将这么多工具合并为一个在纸面上听起来没有那么好。
第三部分 - 随机想法
- 如果 Bun 在2012年出现,它会内置 Grunt。
- 如果 Bun 在2014年出现,它会内置 Gulp。
- 如果 Bun 在2016年出现,它会内置 Webpack。
- 如果 Bun 在2018年出现,它会内置 Rollup。
- 如果 Bun 在2020年出现,它会内置 ESBuild。
- 2026年会发生什么?
2014年,Meteor JS 出现并承诺在一个前端/后端框架中完成所有事情。它会为您处理 websockets,并进行 DOM 的响应式更新,假设后端成功但如果请求失败则自动回滚 UI,使 UI 感觉非常快速和敏捷。它允许多人在同一页面上实时交互内容。而您所要做的就是使用他们的一体化 CLI 在本地运行您的项目,并使用您自己的自定义项目名称部署到免费的在线测试床。
2023年,我尝试再次运行我的2014年 Meteor 项目,与项目兼容的 CLI 版本不再存在,没有完全重写整个项目到最新版本的 Meteor,该项目无法在本地运行或部署。2014版本的所有文档都消失了。
我以前看过这部电影,我知道它如何结束。
第四部分 - 最终想法
在这篇文章中我对 Bun 非常苛刻,不是因为它很糟糕,而是因为它几乎是好的。人们会很兴奋地尝试它,却没有意识到所有的缺点。再次,就像 Yarn 一样,我对 Bun 也相当兴奋。但我已经控制了我的兴奋,从实用和历史的角度看待它。
如果 Bun 真的做到了它声称的一切,那么我100%会支持它。但是不可移植的代码,完全缺乏 Windows 支持,以及他们做出的一些短视选择让我回到现实。
我希望这些批评会导致 Bun 的改进。我希望这种思考过程将允许其他人从更谨慎和深思熟虑的角度看待 Bun。我希望这些关于 Yarn 和 Meteor 的故事能让我们作为一个社区从过去中学习。
第五部分 - 我对未来的预测
- Bun 挑选的大多数项目将在未来一年左右获得性能改进,缩小它们与 Bun 之间的差距。
- 您将开始看到越来越多的仓库在它们的 README 中提到 Bun,可能是独家的。
- 所有在6个月后辞职第一份开发工作成为 YouTube 编码影响者的开发人员都会制作一个"BUN 是未来 OMG"视频,并带有这个缩略图。希望它能诱使人们观看他们关于 Bun 的12部分教程系列。点赞并订阅。
- 我们还没有完善我们的工具。随着我们继续发展并发明更新更好的选择,Bun 将难以跟上,人们将慢慢减少使用它,因为他们变得不耐烦,愿意安装依赖项,如果这意味着一个比他们拥有的更好、更实用的解决方案。
- Bun 可能会存在大约5年。这似乎是大多数类似工具的寿命。
- Bun 最终会有非常非常好的 Windows 支持...可能就在人们停止使用它的时候。
- 由于某种原因,Bun 从不添加版本管理器,而是出现4个竞争选项,都以不同方式糟糕。
- 20XX年,我们终于将最后一个 CJS Node 模块转换为 ESM。这只有在人类最终屈服让 AI 接管后才可能实现。值得吗?
- 乔拜登将获得第二个任期,但是,没有人真正对此感到高兴。
- 事实证明,那个 Yarn 家伙确实看到了大脚怪。现在我为取笑他感到难过。老实说,《哈里与亨德森一家》可能值得重看。
- Vue 仍然比其他一切都好,但人们只会使用 YouTube 编码者说的热门新事物,因为如果不是,他们为什么要制作20个关于它的教程视频?
- 他们将重拍《绝命毒师》,而且不会很好。
- Primagen 聊天中的某个人实际上第一次是对的。你知道他在 Netflix 工作吗?