瞎扯淡 前端根本不需要构建!“技术邪教”Ruby on Rails 之父再出激进言论!

nuanshuidai · 2023年10月20日 · 最后由 mikasa 回复于 2024年03月06日 · 2082 次阅读

在近日的 Rails World 大会上,Ruby on Rails 之父、37signals 联合创始人兼首席技术官 DHH(David Heinemeier Hansson)发表了观点称,最快的打包工具就是没有构建 (No Build),有了 HTTP/2 以及浏览器原生支持 ES Modules,前端根本不需要构建。

“复杂性已经堆叠得太高了”

“我们正在构建一切,一切的一切。”DHH 说道。目前,市面上正不断涌现种种令人兴奋的新框架和新库。“新生的事物太多了,可能我们必须得依靠 AI 提供的建议才能想明白该怎么应对。”

DHH 认为,人们似乎获得了越来越多能够创建出略好一点新版本的工具,但投入却一路飙升。这不是正确的方向、也不是理想的发展状态。

DHH 以自己当时开发 Ruby on Rails 的经历为例称,团队最初的立项是 BaseCamp 框架,前后花了约六个月时间,成员只有一位开发者加两名兼职设计师。最终 BaseCamp 建立起出色的业务,多年间创造了数亿美元的收入。“既然我们在 2003、2004 年那会儿就能做到,那么 2023 年我们理应做得更多。”

对于企业需要用很长的时间才能做出一点改进的原因,DHH 认为其中重要一点是,在生产力低下的时代,取得早期成功的那些企业定下了标准,其他人即使意识到自己需要一点不同的东西,也很难做出实质性的变革:要么效果没有大厂同类方案好,要么就是不具备同样的可扩展性。

“根据一位 Twitter 前员工的说法,他们决定脱离 Rails 是因为之前的架构设计不好,于是他们决定转向当时认为更好的 Java 微服务这边。但很长一段时间过去,工作并没有什么进展。他们完成了立项,又雇用了好几千人,但毫无进展。Twitter 的例子基本就是生产力黑暗时代的常态,人们认为工作在推进,但增量收益却极其有限。顺带一提,Airbnb 那边也有类似的情况,这已经成了一种趋势。JavaScript 框架造成的类似问题还有很多,甚至开始拖累整个行业的发展速度。”DHH 以 Twitter 为例论述道。

DHH 还提到,过去 10 年到 15 年间,技术栈分化问题也给开发人员带来了困扰。架构师想要解决的只是他们认为能解决的问题,但未必是真正重要的问题。所以大家需要关注的是能做到哪些以往做不到的事,而每个人都应该努力成为全栈开发者。

总而言之,DHH 认为,过去 10 到 15 年间复杂性已经堆叠得太高了,现在是时候把简单性作为新的目标了。

如何实现“无构建”

就前端领域而言,某种程度上讲,它已经走进了一种“死循环”——虽然它也获得了一定实质性的进展,改变了如今开发 Web 应用程序的基本预期,但紧跟潮流正变得越来越困难。

对于前端的简化,DHH 提出了“没有构建”的理念。“只要存在构建,那就只能提速。如果根本没有构建,那速度不就到头了?”

“最先进的(打包)技术不再是寻找更复杂的方法来构建 JavaScript 或 CSS,因为前端根本不需要构建。现在可以依靠 HTTP/2 和对 import map 的普遍支持来避免打包。”DHH 介绍称。

import map 直译过来是“导入映射”,可以让开发者直接在页面上管理模块,而不需要通过打包构建。“import map 堪称是 Rail 7 中的一次大冒险。”DHH 表示,配合 HTTP2 一道,import map 就构成了一条加载瀑布流,通过一系列独立的脚本让所有的内容都能同时加载,而不必再将 JS 拆分成一个个包。开发者可以更轻松、更顺畅地使用 esBuild,甚至不再需 Bun 的协助。

“No Build”还具备其他一些奇妙的功能,例如用户可以在任何网站上直接查看源,其内容不涉及任何源映射、不需要任何捆绑,它们就是开发出所编写的文件,未必是编译的纯 JS 文件。一切都能直接交付、不需要经过构建,直接在浏览器端呈现。

alt 文本

对于 Gamil 那种极为复杂且充满交互的产品,DHH 认为,HAML 可以解决。“HAML 为此而生,我们可以借此编写出纯 JS 代码而且无需任何构建。这让我非常兴奋,也是我们目前的主要开发方式。”

没有构建的理念正在迅速普及,如今也已经进入了 CSS,并推出了大受欢迎的 CSS 嵌套功能。现在所有浏览器都支持 CSS 编译,所有浏览器都支持自定义属性即变量。

DHH 透露,现在 37 Signals 的新应用开发中也在运用这两大功能:无需构建 JS 代码和无需构建 CSS。“之前我们就考虑过使用嵌套和变量来回避构建。事实证明没有构建不仅是可能的,而且具有极其重大的意义,我们耗费了约十年时间才破解这种复杂性。”

DHH 表示,绝大多数静态站点不需要花哨的构建管道。Server Side Includes(SSI)被严重低估了。他提出可以将一个 Jekyll 站点转换为 SSI。“一旦将静态站点转换为 SSI,我就会将这些简化为一个新工具,让它们变得简单。拥有一种巧妙的石器时代技术,可在 5 秒内自动推送更新。只需为其提供一个小型虚拟机即可,每月花费应该不会超过 5 美元。”

DHH 还表示,这一年半以来,37 Signals 开始转向 propshaft,这个新库用于在 Rails 侧无需编译的前提下提供资产管道。它的基本功能只有两个:为所有资产提供加载路径,以便在任意视图中访问任意位置上的 gem 及其他资产;提供摘要标记,从而确保拥有良好的远期动态缓存。

在推特上,DHH 还展示了公司主站的性能表现,他表示 HEY 主要应用运行的 JavaScript 代码没有经过构建。“我认为我们在 No Build、import map 和大约 100 个单独的 JS 文件方面做得很好!我们发送 500kb 的未压缩 JS,而 Gmail 则发送 10mb!”

alt 文本

“在 es6 以及 JS 世界中一系列基础进展的支持下,如今的前端代码已经做好了跨越复杂性之桥的准备。我知道,现在的方案仍然有点复杂,但从结果上看所有付出都绝对物有所值。”DHH 表示,“我们目前最应该做的是:在现代 Web 应用程序的构建过程中,剔除一切形式的 JS 捆绑或转译。当然,这样的未来是等不来的,我们应该从现在开始转换自己的开发思路。”

真有用还是噱头而已?

对于 DHH 提出的“No Build”理念,Vercel CTO Malte Ubl 在推特上表示,他们已尝试过,但结果是行不通。因为在 HTTP2 中,每个请求的开销仍然非常大,并且存在并发限制,此外还会出现瀑布流和低效压缩。目前,“打包”对于高性能网站来说是无法绕过的。

DHH 不认可 Malte Ubl 所说的“行不通”。他表示,这就是技术讨论的奇怪之处。即便已经有案例证明项目能完成大规模任务(如 Rails 之于 Shopify),但人们也会声称它不能进行扩展。或者已顺利使用某种方法多年(如 no build JS 之于 HEY 网站),也会有人说这套“行不通”。

还有人觉得这个只是噱头。推特网友“Viking”表示,自从移除 TypeScript 后,DHH 越来越激进了。甚至有网友称 DHH 散发出令人不安的“邪教领袖”气息。

alt 文本

开发者 Nander 表示,“构建时间并不重要,重要的是 FCP(First Contentful Paint,从开始加载到页面内容的任意部分在屏幕上渲染出来的时间)。导入映射时间并不比位于同一服务器上的 RSC(构建步骤)和最小化捆绑包(构建步骤)快。”

“Chrome 删除了 HTTP/2 的多路复用,它并不比捆绑更有效率。HTTP/3 已经解决了这个问题,并且可能证明捆绑已经成为过去。但据我所知,还没有人尝试过 HTTP/3 多路复用 esm 服务器。Node、Deno 和 Bun 甚至还没有支持 HTTP/3。”Joe Pea 说道。

还有开发者指出,不打包=把开发细节暴露给用户,浏览器原生支持不等于高效。build 是快了,但运行时慢了的话还划算吗?前端工程化的一个重要里程碑就是引入了 build 步骤,让开发体验和用户体验分离,特别是几百个不同版本的、不同浏览器的用户体验完全分离,这才让开发者真正解放了。

有开发者很喜欢这个主意。Rails 开发者 Niklas Häusele 表示,“我喜欢用‘No Build’的方式进行本地开发。无需等待即可刷新,这就是最高的生产力。我甚至删除了 tailwindcss-rails 并将其替换为 tailwind CDN,以避免必须在本地运行任何内容。对于 tailwindcss-rails gem 来说,这将是一个有趣的默认值。”

对于 DHH“没有构建”的理念,你有什么看法?欢迎在评论区留下你的想法。

参考链接:

https://twitter.com/dhh/status/1713615147393323408

https://twitter.com/cramforce/status/1712265070213050390

https://twitter.com/cramforce/status/1712265070213050390

https://world.hey.com/dhh/you-can-t-get-faster-than-no-build-7a44131c

本文转载来源:

https://www.infoq.cn/article/9k37mArAJlY708eGOkVP

我认为没毛病,技术就该结合商业,不然没法驱动。既然商业,那么综合成本考虑(人员成本、语言开发成本、运营成本)。 包括他们“下云”的决策,也是在达到一定商业体量后,在成本的考虑上做出的决策。 包括把队列中的 db 改成 disk db 取代 redis db,降低 20% 效率,节省 80% 成本,确实是有收益的 我相信 DHH 的观点,也是基于自己的实践得出的结论。这些观点,都是围绕着商业项目的“降本增效”。

同意楼上。DHH 总是结合实践来说明问题。

前端娱乐圈总是嘴嗨更多。

如果观点不能跟随现实发生改变,其实就是一种固执己见,偏执人格障碍。

这个问题其实很简单,当网线足够宽,以前的那些省流的骚操作当然可以一并去掉了。就像现在,电话线上网那时候的“下载器”很少被人提起;直播、网上看剧成了主流。

其实是一样的。

基础设施好了,辅助设施就可以下架了。

话说我最近有看到一个猛士,听信了 DHH 邪教做法,竟然在自己的办公室弄了个破电脑插了 64G 内存部署了一堆服务,用 ngrok 联到 aliyun 上的一台破 2C4G 的 nginx 跑。。。。。。

jicheng1014 回复

听上去是个好主意

没价值滴

DHH 肯定是在宣传自己的理念了。前后端一体是个好的想法,只是某些时候可能会比较费脑子。举例说,我有一个 3 个标签页的结构,如果用 hotwire,还得纠结一下这三个标签是一次渲染出来还是分批渲染。分批我还得搞 3 个 action 这种事情。React 则胜在简单粗暴,上就对了。

至于打包开销,自从有 esbuild 后,一切都很轻松愉快。第一次从 webpack 换过来,真的是把一分钟的时间缩到了 2 秒内。

我倒是希望前后端一体话可以有更加容易理解和执行的解决方案,能让 Web 开发更加简化。

ericguo 回复

如果是 不太涉及到交易的,完全可以这么搞,懒得维护数据库就用远程联数据库 并不慢很多

复杂组件用 stimulus 太难实现了,特别是现在很多前端项目动辄上千个组件,不用 React/Vue/Solid 这种声明式前端 UI 库根本 hold 不住。但我觉得 DHH 会说:“为什么不保持简洁的前端页面?”😂

现在很多项目,特别是中后台,PM 对前端组件的复杂度无节制的依赖和设计,确实是搞得大家都很痛苦——运营学习成本高,研发开发成本高。

Wake up, bosses! This is your solution. Give us the chance to use this attractive technology before you get bankrupt.

其实吧,我觉得任何极端的做法都不可取,万事讲究一个度,物极必反,想想 WEB 最开始开发是什么样子?再想想前端层出不穷的各种库穷极了又是什么样子? 所以,阴阳调和、各伺其则是最好的办法。

Xenofex 回复

React 怎么就简单粗暴了?不用服务端交换数据嘛?如果不用,hotwire 都没什么事,页面请求的时候都渲染出来了😂

willx 回复

stimulus 主打一个驱动现成组件,比如这段 HTML DOM 显示出来了以后,开始初始化某个现成的组件,而不是做组件。React 的确可以做到前端用其他工具都做不到的复杂组件,但如果全站全用,甚至接管路由,感觉有点不尊重用户的内存了,比如今天试用的金山网盘,直接吃掉 1.6G 内存,其中当然有 Electron 的问题,但是前端代码无节制的使用内存所占比例也肯定不可缺少。Notion 这边就做的比较好,基本占用内存在 800 兆以内。

所以我觉得其实还是应该对现在的中后台网站设定一个内存占用指标,比如 1G 以内。毕竟不是所有用户的电脑都有那么大的内存。8G 内存的电脑还是很多的,尤其是经济下行了,更新电脑几乎也是 6 年以上了。React / Vue / Solid 前端框架在这方面其实从来没有考虑过,我倒是觉得应该考虑,手机电脑的内存永远是有限的,以后的头显设备内存就更加有限了。

有一点疑问,像 codemirror6 这种复杂的包,把功能分成了很多小包,是如何 0 构建使用呢?直接一个个手动把包在 importmap 里指定?

theway 回复

可以混用,一部分打包一部分不打包。如果有洁癖想要完全不打包,就把编辑器独立一个项目打包,就好像 trix editor。

Rei 回复

这样岂不是又是非 0 构建了?

ericguo 回复

其实没有那么夸张,目前最新的 Chrome 可以实时显示每个网页的内存消耗了,目前我们这边最复杂的后台(5000 个组件,30 多个页面,前端路由,redux 全局状态管理),用一段时间后大概也就只吃了 400M。Electron 这种技术主要是包了个浏览器,确实内存杀手,但光页面内存的消耗在今天看来其实真的还能接受。

Xenofex 回复

Elixir 语言的 Phoenix LiveView 你觉得怎么样? /

标题党了

至少可以把 bundle 步骤给去掉😀

willx 回复

我这里有 120 个页面的,差不多是 1G,其实现在技术趋势已经可以看出了,如果这条路可行,那就不用搞微前端了。

ericguo 回复

120 也太夸张了😂,但即使是 120 张页面,前端的异步加载做好、状态管理拆分一下,不会这么夸张的。除非用户在不刷新的情况下,把所有的页面、所有的组件都访问一遍……

另外微前端不是用来解决性能问题的,主要是解决工程问题的,可以看看 qiankun 的文档上描述自己的核心价值是什么 https://qiankun.umijs.org/zh/guide#%E4%BB%80%E4%B9%88%E6%98%AF%E5%BE%AE%E5%89%8D%E7%AB%AF

MarkHoo 回复

不要老觉得别人的女朋友漂亮

基于 WebSockets 和 SSR 用 Rails 和 Hotwire 你不缺

Action Cable 和 morphdom 结合一下,简单又灵活的达到效果

刚特意搜了一下,果然是有大哥封装了这些常用的操作 turbo_power

willx 回复

你说的也对 在这之前可能编译时间已经促使不得不分开开发前端页面项目了 不过文档硬要把锅推给巨石应用也算服气的 你说你框架就是不 scale 不就好了 大家都是技术人员 这种小心思有必要吗?字节至少还搞了 rust 的建构打包器 阿里真的是遇到问题绕着走啊!

jicheng1014 回复

学到了……

losingle 回复

以下仅代表个人经验:

用 hotwire 的时候,不免会思考,这个交互是放在服务端还是客户端。这点界面变化,我是为了渲染接口统一走后端,还是用 dhh 的 stimulus 在前端搞一搞?

实际使用下来,vue 2 那种模式是最方便的,把他当成一个强效版 stimulus 就可以了。hotwire 拉 html 不够的时候,自然的引入一个 vue 2 做前端渲染,保证最大的灵活性。

Xenofex 回复

Vue 和 React 都是趋向于把问题复杂化, 我个人是非常讨厌在 rails 项目中见到他们的影子。

hotwire 才是那个不需要你去担心“这个交互是放在服务端还是客户端”, 遵循的优先级很简单 turbo frame -> turbo stream -> javascript

需要 登录 后方可回复, 如果你还没有账号请 注册新账号