Lovable 用 Rust 重写了 Vite……(算是一部分吧)
BBetter Stack
Computing/SoftwareSmall Business/StartupsInternet Technology
Transcript
00:00:00用 Rust 重写的项目又多了一个,这次是 Vite 开发
00:00:03服务器,由 Lovable 团队使用 Rust 进行了重写,据说实现了 4 倍的内存
00:00:07优化和 2 倍的冷启动速度提升。接下来我们就来深入调查一下这个说法,因为它可能
00:00:12有点误导性,然后再看看这是否是你未来应该切换使用的工具,
00:00:15以及 Vite 的作者认为这对开源的未来意味着什么。
00:00:24我所说的这个项目叫做 OJ,也就是 Orange Juice,它的理念是提供一个
00:00:29Rust 二进制文件,可以直接指向我现有的 Vite 项目并直接运行。它读取我的 Vite
00:00:33配置,依然运行现有的 Vite 插件,但底层的开发服务器,比如文件
00:00:38监听器、模块图、热模块替换和 React Fast Refresh,全部用 Rust 进行了重写。
00:00:44有趣的是,这是利用 rolldown 和 oxy 实现的,而 Vite 本身也在使用它们,并由 voidzero
00:00:49负责维护。为了亲自测试一下,我构建了一个 TanStack 应用,看看使用
00:00:53Vite dev 和 OJ dev 运行之间是否有差异。从表面上看,它们的工作方式几乎一模一样,
00:00:58所有功能都能正常运行,比如服务端渲染、注水(Hydration)、服务端函数、快速刷新、
00:01:03动态文件路由、服务器路由、Tailwind 以及资源导入,但深入研究后,
00:01:07我确实注意到了一些细微的差别。第一个是在这里的快速刷新上。如果我编辑一个文件,
00:01:13Vite 的计数器会保留其状态,但在 OJ 下,计数会重置回零,
00:01:17这表明 OJ 进行的是全页刷新,而不仅仅是发生变化的组件。我决定
00:01:22在一个没有使用 TanStack Start 的纯 React 应用中测试相同的行为,
00:01:26有趣的是,在这里它似乎又能正常工作了。这里的相同编辑保持了计数不变,
00:01:30并且它没有更新整个页面,所以它看起来在做真正的热更新。所以我不知道为什么
00:01:35TanStack Start 和纯 React 应用之间会有这种差异,也许这只是他们
00:01:39尚未考虑到的边缘情况之一。我注意到的第二个差异是在
00:01:42服务端函数上。这个服务端函数从应用内部测量开发服务器整个进程树的内存,
00:01:46在这个应用中,使用 Vite 时跨两个进程大约占用 380MB,而在 OJ 下,
00:01:53同样跨两个进程大约占用 320MB。所以像这样的小型应用,内存
00:01:59使用量大致相同,OJ 只是略微领先一点点。这是否意味着这个项目
00:02:04完全没有用呢?并不是,因为这并不是 OJ 真正要解决的场景。OJ 实际上
00:02:09在非常大的应用上表现最好。当我在一个拥有 5000 个组件的 React 应用上测试时,使用一个脚本
00:02:14来启动每个开发服务器代码,在真实的 Chrome 浏览器中打开页面,当最深层的组件
00:02:19进入 DOM 时停止计时,然后采样整个进程树的内存,OJ 的普通
00:02:24模式在首屏渲染速度上比默认的 Vite 快约 1.7 倍,且内存消耗
00:02:29大约只有四分之一。公平地说,Vite 8.1 确实推出了一个名为打包开发模式(bundled dev mode)的实验性功能,
00:02:34如果开启该功能,Vite 实际上能达到 1.18 秒,这甚至比 OJ 的
00:02:40普通模式还要快一点,但它并不能节省内存。而 OJ 也有一个打包模式,使用该模式时
00:02:45速度会更快,大约为 0.89 秒,同时把内存保持在 Vite 的四分之一左右。
00:02:51因此 OJ 确实具有一些实实在在的内存优势,而这也正是 Lovable
00:02:55开发这个项目的初衷。Lovable 的预览环境运行的是真实的 Vite 开发服务器,Lovable 表示他们每天大约运行
00:03:00100 万个这样的沙盒,在如此庞大的规模下,资源消耗
00:03:04变得至关重要。因此 Lovable 开发了 OJ,以获得能即时启动并保持轻量的预览体验,
00:03:09同时又不必放弃最初让应用运行起来的生态系统。
00:03:13他们还针对该用例(即 AI Agent)做出了相当酷的设计决定。在编辑时,
00:03:17人类通常一次保存一个文件,但 Agent 可能会在极短时间内连续写入 10 个左右的文件,
00:03:22Vite 会将每一次保存都视为一次单独的更新,但在 OJ 中,文件监听器、
00:03:26模块图、编译器和热更新属于同一个流水线,因此这种爆发式的写入会被合并为一次更新。
00:03:32还有一个可开启的关卡机制,更新会被保留,直到 Agent 本身
00:03:35向刷新端点发送请求,这样预览只会应用已完成的修改。你可以看到这
00:03:40是一个非常具体的项目,专门用来解决 Lovable 自己的业务场景,这恰恰也是 Vite 作者尤雨溪
00:03:45所认可的。他在这条推特中的第一个观点是,这是一个令人印象深刻的项目,很好地解决了
00:03:49Lovable 自己的问题,但它并不是对 Vite 的完整重写。它只是开发服务器,
00:03:54而且它也是基于 void0 维护的 Rolldown 和 Oxy 构建的,所以谈不上替代它们。
00:04:00OJ 中的解析器、转换器和生产环境打包器都是 void0 的产品,
00:04:04Lovable 只是围绕它们编写了服务器。本质上你可以这样理解:Vite 是一个驱动 Rust 的
00:04:08Node 进程,而 OJ 是一个驱动 Rust 的 Rust 进程,中间夹着一层
00:04:13JavaScript,以便它仍然可以与 Vite 的插件 API 进行通信。尤雨溪接着还指出,
00:04:17OJ 之所以能这么快,是因为它只支持一种应用形态。OJ 实际上只支持
00:04:22React 应用,也就是 Lovable 生成的那些应用。而 Vite 则必须
00:04:27支持各种框架、各种奇葩配置以及围绕它构建的工具,并且它刻意将
00:04:31像 ESBuild 或 React 插件留作独立的包,以便你在需要时自行添加。
00:04:36在此之后,他还挑出了基准测试中的漏洞。博文里的 Vite 冷启动测试
00:04:40包含了 Vite plugin checker,它会在后台 Worker 中运行 TypeScript,但 OJ 实际上
00:04:45并不支持该插件,因此它完全跳过了这项工作。他还指出,Vite 在开启打包开发
00:04:50模式后,冷启动速度更接近 OJ,这与我们看到的数据完全一致,不过他确实
00:04:55承认 OJ 占用的内存要少得多,而 Vite 应该把改善这一点作为目标。
00:04:59尤雨溪在这条推特中的最后一个观点是我觉得最有意思的。开源的动态格局正在
00:05:03发生变化,由于 AI 的存在,重新实现某样东西的成本急剧下降,因此我们会看到更多
00:05:08他所谓的“定制化开源工具投影”,即在某一个组件的约束条件下重新构建同一个依赖项,
00:05:13以契合特定的用例。他举了 TanStack 的 redact 作为另一个例子。未来可能会出现一种情况:
00:05:19维护者不再被成千上万的劣质 PR 所淹没,而是每个人
00:05:23都维护自己的“定制 Fork”。他说坦白讲,他不确定这是否是一件好事,但他
00:05:28认为这很有可能是未来几年内会发生的事情。因此一方面,定制 Fork 对于维护者来说
00:05:33比处理一大堆劣质 PR 要好,但我们确实面临着生态碎片化的风险。我想
00:05:39只有时间才能证明这一切将如何演变,以及开源的未来会是什么样子。
00:05:43总的来说,除了 Lovable 之外,这并不是一个其他人会去使用的工具,除非你
00:05:47也面临在沙盒中运行数百万个 Vite 开发服务器的完全相同的问题。我是说,
00:05:52你真的在自己的电脑上注意到过 Vite 变慢或者占用过多内存吗?我个人
00:05:57并没有,但这依然是个很酷的项目,他们能做到这一点真的很棒,
00:06:01欢迎在评论区告诉我你的看法。顺便点个订阅,一如既往,
00:06:04我们下期再见。
00:06:09下期再见。
Community Posts
No posts yet. Be the first to write about this video!
Write about this video