软件”臃肿”一点,又何妨?

在高速CPU、千兆字节内存和太字节存储的时代,软件效率已成为被忽视的领域。许多人认为如今优化软件的必要性降低了——毕竟处理器够快,内存又便宜。他们主张应聚焦其他方面,如开发者效率、可维护性、快速原型开发等,并常援引唐纳德·克努斯的著名箴言:

过早优化是万恶之源。

目录

  1. 当今软件臃肿问题有多严重?
  2. 膨胀现象中很大一部分实为权衡取舍
  3. 但确实,膨胀的很大一部分也是有害的
  4. “瓶颈”依然存在且仍在被优化
  5. 过晚的优化同样是问题根源
  6. 结论

当今软件臃肿问题有多严重?§

历史上计算机的运算能力和内存都极为有限。CPU和内存价格昂贵。程序员深受CPU速度和可用内存的限制。为使程序适应这些有限资源,需要投入大量工作。因此1970-80年代的程序普遍采用机器码或汇编等低级语言编写,这并不令人意外——这类语言能让程序员对每个字节和处理器指令实现终极控制。

元素周期表

随着时间推移,内存和CPU(以及所有硬件)逐渐降价。这减轻了技术限制,使得更高阶语言得以应用,最终催生了垃圾回收语言的兴起(如Java、C#、PHP、Python、JavaScript等)。

图0:软件软件臃肿化进程

对比新旧软件的系统需求时,常令人震惊。仅以Windows 11计算器为例(更不用说完整操作系统),其内存占用就超过30MiB(实际可能更高,因未计入共享内存),而Windows 95仅需4MiB内存即可运行。

图1:软件仅Windows 11计算器就占用超过30MiB内存。它不可能执行如此复杂的操作,以至于需要比Windows 95多出7-8倍的内存。

再举一个更极端的例子。超级马里奥兄弟游戏仅占31KiB(或40KiB,实际差异微乎其微),实际内存占用仅2KiB。但下方这张高品质WebP图片(完整保留原始像素,无损压缩)竟高达54KiB——比游戏本体还要大!

图2:软件这张加载后的图像近54KiB,竟比仅需少量ROM和2KiB内存的游戏本体还要大!

这种臃肿现象很大程度上是权衡取舍的结果§

乍看之下这简直不可思议,开发者们大概根本不在乎效率吧?其实情况更复杂,其中相当一部分问题并非源于开发者的能力不足或懒惰。

当今软件解决了一些在1990年代及更早时期并不突出的问题。以下是几个例子:

  • 层级与框架 。现代软件往往更为复杂。开发者通常不会从零开始编写软件,而是借助各类库或框架。例如前文提及的Windows 11计算器,便是基于C++/WinRT构建的UWP/WinUI/XAML应用。你加载的UI框架、布局引擎、本地化支持、输入法、矢量图标、主题管理、高DPI适配等组件,其共享DLL文件始终驻留在内存中——即便任务管理器仅在应用”工作集”中显示部分内容。
  • 安全与隔离 。当今安全至关重要。沙箱、代码完整性、ASLR、CFG、数据执行保护等机制会增加进程、映射和元数据。这些在早期软件中并不常见。
  • 健壮性与错误处理/报告 。与前项相关。现代软件通常结构复杂且存在大量边界情况(有时还需集成第三方组件),因此必须处理并记录所有可能的错误/故障。这些安全措施同样会增加额外代码量。
  • 全球化与无障碍支持 。完整Unicode支持、从右到左文本处理、复杂脚本支持、屏幕阅读器适配、键盘导航、高对比度模式/动画效果等功能均需额外代码与资源。
  • 容器与虚拟化 。将应用程序与其精确的运行时/依赖项打包成镜像,通过Docker在任意主机上作为容器运行。开发、CI、预发布和生产环境使用相同容器可减少环境漂移导致的缺陷。当需要在与主机操作系统不兼容的环境中运行程序时,虚拟机仍是理想选择。
  • 工程权衡 。我们接受更高的基础门槛,以实现跨设备更快、更安全的代码交付。硬件性能已提升约三个数量级。开发者时间往往比内存或CPU周期更宝贵。现代软件通常由多人(甚至整个团队)协作开发,这要求代码结构具备可维护性与协作性,例如模块化、可扩展性/灵活性、代码/架构模式等。试想为某个业余爱好者用汇编语言编写的古老超优化游戏添加功能。若无原作者协助,这将极具挑战性:代码难以理解(更像是逆向工程),修改可能破坏某些”精巧但脆弱”的代码等。我们当然不希望出现这种情况。

图3:软件性能之外,还有其他同等甚至更重要的考量。

但确实,膨胀代码中很大一部分确实很糟糕§

话虽如此,许多冗余并非权衡之下的产物,而是能力不足或懒惰所致。例如为琐碎功能使用库或框架,或是对算法复杂度缺乏理解。许多网站因引入数十个(有时上百个)可疑依赖而臭名昭著,这些依赖不仅拖累性能,还可能引发安全漏洞和维护难题。而当今的人工智能技术正使这类问题呈倍增态势。

部分问题还源于软件复杂性。当软件规模庞大且结构复杂时,开发者往往只关注局部模块。软件开发者不了解系统整体运作机制是普遍现象,这自然会导致效率低下。设计欠周全或结构/管理不善的项目会加剧此问题,有时甚至引发代码腐化的恶性循环。

过度工程化同样是臃肿的根源:

  • 为微型应用部署微服务
  • 通用插件系统
  • 依赖注入森林
  • 仅使用一次的”以防万一”接口
  • 采用SPA架构并为静态内容配置全局状态(导致简单页面加载过程臃肿)。
  • 为微小收益堆砌多重构建步骤/工具。

最后,对容器技术的过度迷恋同样令人担忧。容器往往导致启动时间延长(即使在SSD上也相当耗时),并增加内存和CPU消耗(Ubuntu Snap就是典型例子)。遗憾的是,容器作为缓解普通桌面应用兼容性与安全问题的便捷工具,具有极强的吸引力。

“瓶颈”依然存在且仍在优化§

许多程序仍存在少量关键代码区域需要优化,例如某些数据库查询或长时间运行的函数。

高度优化的程序或其部分组件仍存在巨大需求,且短期内不会消失。以下是此类软件的极小部分示例:

  • 编解码器 :dav1d(AV1)、x264/x265(H.264/265)、libjpeg-turbo。
  • 归档器/压缩器 :zstd、xz/LZMA、brotli、libarchive。
  • 虚拟机/即时编译器 : HotSpot(JIT层级+GC调优)、V8/JavaScriptCore(内联缓存、TurboFan)、LuaJIT(追踪式JIT)。
  • 标准库 :glibc、musl(轻量级且可预测)、现代C++ STL(小缓冲区优化、节点式与扁平容器)、Rust标准库(零成本迭代器)。
  • 加密库 :OpenSSL / BoringSSL / LibreSSL(常数时间、向量化原语)。
  • GPU驱动程序
  • 游戏引擎
  • 操作系统内核

此类软件永不消亡,只是迁移至特定领域或成为更高层软件的底层”骨干”。

过晚优化同样是祸根§

虽然为假想收益牺牲设计与正确性而进行的过早优化有害,但延迟优化同样不可取。你仍需在早期选择正确的算法和架构,因为错误决策可能在后期反噬。在早期阶段,O(N)O(N2)算法的选择通常依然至关重要。

结论§

适度臃肿其实无妨,甚至有益。若没有这种冗余,创新就难以涌现。诚然,我们能将许多事物超优化,将应用体积缩减10至100倍。但多数情况下,这不过是用开发者时间换取一场得不偿失的胜利。另一方面,正如其他事物,过度膨胀同样有害——我们也目睹过这种情况。因此,过晚的优化同样可能成为问题。

本文文字及图片出自 Some software bloat is OK

共有 118 条评论

  1. 软件臃肿绝非良策。技术债务或许尚可接受,而明知故犯的技术债务可能导致软件臃肿。但若主张(某些)不加斟酌的软件臃肿无可厚非,这正是我们拥有想象中最快机器,却仍面临用户界面无法跟上键盘输入速度的根源。

    断章取义引用克努斯同样助长了臃肿之风。

    > 程序员耗费大量时间思考或担忧程序非关键部分的速度,而这些效率追求在调试和维护时反而产生严重负面影响。

    > 我们应当忽略97%的小幅效率提升:过早优化是万恶之源。但对于那关键的3%,我们绝不能错失优化良机。

    • > 但若认为(某些)软件膨胀无需顾虑,就会出现这样的局面:我们拥有想象中最快的机器,界面却仍跟不上键盘输入的速度。

      这真的算问题吗?该博客专门讨论权衡取舍,并用整节篇幅阐述工程设计中的权衡。感知性能正是其中一项权衡。

      你抱怨UI跟不上键盘输入速度。我以Visual Studio Code为例反驳:其UI虽不如原生GUI框架敏捷,却实现了跨操作系统与桌面环境的一致顶级用户体验。这难道不是胜利吗?有多少项目能做到这点?

      该博文还专门论述了臃肿化中大量冗余代码的危害性。

      • > 你抱怨 UI 跟不上键盘输入速度。我以 Visual Studio Code 为例反驳:虽然其 UI 响应不如原生 GUI 框架敏捷,但我们实现了跨操作系统和桌面环境的一致顶级用户体验。这难道不是胜利吗?有多少项目能做到这一点?

        这算胜利吗?为什么?跨平台一致性属于品牌战略和商业目标,而非工程目标。一致性本身不指向任何方向,它只是让产品更熟悉、更易于无成本接纳。整天坐着不动,从不锻炼,岂不是更轻松?

        “大家都这么做”或“大家都用这个”,从来不等于它就是好的。

        值得注意的是:我最敬重的工程师们,以及那些创造出我乐于使用工具的人,无一使用VSCode。我敢肯定多数人会将此解读为对他们首选编辑器的攻击——“远离异教徒!”但愿足够多的人能明白,这并非针对他们或其编辑器的攻击,而是我主张选择最佳方案而非最易用方案。他们能否使用VSCode?当然可以。他们不选的原因在于:经验越丰富,越能看清臃肿功能如何阻碍开发效率。

        • > 值得注意的是:我最敬重的工程师们,以及那些打造出我乐于使用产品的开发者,无一使用VSCode。

          好奇他们用什么?

          • 虽然不是楼主,但我们公司有相当数量的高级(及以上)工程师使用默认的vim或neovim(无插件或自定义)。

            • 提醒一下,如果你用macOS,系统自带的vim版本和bash一样老掉牙。如果遇到vim运行缓慢的问题,建议升级到新版。

              不过Homebrew能帮你搞定!

      • 好吧,但像Zed这样的框架几乎能媲美原生GUI框架的响应速度,同时提供一致的用户体验。看起来他们并未在这方面做出任何妥协。

      • > 感知性能正是这类妥协之一。

        感知 性能绝不该成为权衡点,只有 实测 性能影响才可能如此。

        我的2020款iPhone SE升级iOS 26后出现长达2秒的输入延迟,实在令人失望。即便延迟在0.3毫秒范围内(从实测性能角度看依然糟糕),我也能接受。

      • 这确实是个问题。技术栈的每个层级都需要权衡取舍,而当越来越多的层级将权衡方向偏离速度时,影响就会呈倍增效应。

        跨平台UI的设计绝不意味着必须牺牲响应速度,更不意味着Electron是唯一选择。

        VSCode在现有方案中做得够好吗?或许是,或许不是。但关键在于我们应该聚焦于优化方案本身。

        在两个糟糕选项间做取舍,意味着你已经输了。

      • Visual Studio Code 的用户体验糟糕——部分源于其基于 Electron 的架构无法媲美原生 GUI 框架的响应速度,同时也存在诸多其他问题。我并非自愿使用它,更深感遗憾的是,许多我希望使用的编程工具刻意设计为 VSCode 插件,而非适用于任意编辑器的通用工具。

        我在VSCode中确实遇到过界面显示滞后于键盘输入的问题(偶尔发生),其他基于Electron的应用也常有此类情况(频率更高——或许它们在优化方面不如VSCode投入精力)。仅凭这一点,我就对Electron生态系统颇为反感,并对开发替代性跨平台渲染器的项目充满兴趣。

        我最终希望看到Electron成为一个死项目,这样我就再也不用遇到那些有趣、实用或必须使用的软件——它们之所以采用Electron开发,仅仅因为这是开发者最显而易见的选项。

  2. “开发时间比性能更重要”的信条将糟糕的性能视为软件的根本问题,而实际上性能低下只是软件复杂性不断增长的症状。我相信每个导致软件臃肿的程序员都曾认为自己的改动合理。每个倡导微服务的人也坚信自己在解决现实问题。症结在于我们从未将复杂性本身视为问题。

    在机械工程、土木工程乃至工业设计等物理学科领域,存在着追求简洁的天然倾向。每次迭代都更精简、更统一——更美观,因为它更接近完美物体的境界:精准完成必要功能,毫无冗余。但在软件领域,或许因难以窥见计算机内部运作,我们缺乏追求简洁的动力。每次新版本的LLVM二进制文件都比前版更大,每次更新的HTML规范都更冗长,每次诞生的JavaScript框架都更抽象,每次升级的Windows系统都更臃肿。

    结果是基础操作都变得困难。手动绘制屏幕变得困难,因为图形标准日益复杂且支离破碎。于是你构建网页应用,但从零开始实现却很困难,因为纯JS的DOM API并非为应用设计而生。于是你转而采用框架,却发现框架本身已被多年累积的冗余代码和历史决策所埋没。计算机科学的诸多领域皆是如此——抽象层层叠加,抽象中又藏着抽象,宛如来自地狱的复杂性分形。诚然,每层都解决了特定问题,但层层叠加反而催生了新问题。适度的软件膨胀尚可接受,但全面的软件膨胀则有害无益。

    安全性、可访问性与健壮性固然是崇高目标,但若想打造卓越软件,不能简单堆砌这些特性。我们必须解决如何在不大幅增加复杂度的前提下融入这些要求——这才是真正的难题。作为工程师,我们需要建立严守简洁原则的文化;作为人类,我们需要支持不受企业政治拖累的工程实践。

    • 物理工程领域同样存在类似现象。某些产品达到发展瓶颈后便停滞不前,但销售压力依然存在——设计师需要薪酬,产品仍被当作身份象征等等。

      裙装长度便是典型例证。时尚的本质就是变化。当短裙风靡时,时尚杂志就必须推出长裙设计,投入生产并发往店铺以刺激销量。而数百年来,裙装的功能性本质从未改变。

      • 或者人们干脆无视潮流,只在衣物磨损时才更换。

      • 我认为时尚潮流不可同日而语。时尚概念本身无可厚非——旧物淘汰,新物更替,这正是人类超级有机体孕育新思想的方式。可惜资本主义将这种更替推向了非理性的速度,即便在《星际迷航》的共产主义世界里,人们也会厌倦。孕育某种风格的文化能量终将消散,我们永远需要契合当下时代的新事物。

        但服装终究要 赏心悦目 。时装设计师的动力在于优雅地实现服装功能。若在裙摆加装金属滑轨以随意调节长度,便是对优雅的亵渎。诚然新物件具备新功能,设计师或许自诩精妙,但其丑陋本质昭然若揭。然而丑陋的软件与优美的软件往往难辨真伪。正因参与者皆缺乏审美眼光,软件潮流终究沦为丑陋的代名词。

  3. > 仍有大量需求旺盛的优化程序或其组成部分不会很快消失。此类软件仅占极小比例:> … > 这类软件将永远存在,只是迁移至某些利基领域,或成为更高层级软件的底层“骨干”。

    是的。多年来我一直在用C语言构建基于GPU的科学可视化库[1],精心减少堆分配,优化紧凑循环和数据结构,尽可能削减内存占用和运行时间。与此同时,其他人似乎都满足于数百兆字节的Electron式臃肿代码,忍受着数秒延迟和每秒5帧的界面。有时我怀疑自己是否只是另一个时代的遗物。但诸如此类的评论提醒我,我只是在某个利基领域工作,在这个领域里这些优化仍然至关重要。

    [1] https://datoviz.org/

    • 你永远要面对“够用就好”和惯性思维。对大量应用而言,臃肿的Electron应用确实足够用了!

      顺便说一句,你开发的库简直太棒了。不过我记得你页面上也承认过,Matplotlib对许多场景可能已经足够用了。当有人对现有工具极其熟悉时,任何替代方案都必须带来重大变革,才能解决现有低效工具无法处理的问题。

      • 感谢指教。我的库适用场景很明确:当Matplotlib因数据量过大(尤其是3D场景)导致运行极慢甚至崩溃时。

    • 我虽不熟悉该领域,但记得曾用Plotly配合WebGL创建交互式图表处理海量数据点(金融 tick 数据)。这个项目看起来相当有突破性,非常酷!希望您继续推进。

    • 请继续当前的工作方向,我欣赏您的努力和理念。

  4. 怀念当年在互联网服务器上狂玩《雷神之锤1》多人模式(QuakeWorld)的日子。当时只需在游戏目录放置“autoexec.cfg”文件,启动后就能自动执行命令,比如/connect [IP地址]

    从点击.exe启动游戏到进入服务器(地图视角)并完成100%资源加载,全程仅需1秒。真的!桌面图标点一下,咻!瞬间就出现在服务器里开火了。不过这可是约翰·卡马克用C语言写的程序呢 🙂

    再举个例子——我家里有个“ModRetro Chromatic”,本质上是任天堂Game Boy的FPGA版本。这台设备不会像普通Game Boy那样显示标志性的“Nintendo”字样并播放经典音效。当我插入卡带并翻动电源开关时,游戏瞬间启动。这里根本不存在任何延迟。开机即游戏,字面意义上就像当年玩《雷神之锤》那样。

    对比之下——我还有台Steam Deck,启动时间长到有时上完厕所它都还没开机。如今的体验与我记忆中的旧时光简直天壤之别。当年Windows 2000系统下,所有操作都比现代机器流畅得多。我真的很怀念那种感觉。

    • SteamOS这类系统其实能实现秒开机——但需要费心配置,况且大多数用户只会让设备休眠(一秒唤醒),开发者根本不会为此费心。

    • 游戏卡带的访问速度远超同时代任何介质,因为它们本质是ROM存储器。若将Linux、OpenGL、Vulkan等系统置于Steam Deck的ROM中,再用ROM卡带(而非闪存卡)存储游戏,同样能实现瞬间启动。

      Windows 2000在现代硬件上启动迅速。若认为它在当年硬件上能如此迅捷启动,那你可真是戴着粉红眼镜看世界。Windows NT当年虽是臃肿系统,但至少是干净的臃肿——没有间谍软件和其他垃圾程序(除非像我拜访过的某客户公司那样,任由Bonzi Buddy、Comet Cursor之流在敏感企业工作站肆意横行)。

  5. 问题当然在于每个人划定的界限不同,这正是症结所在。

    太多人将“过早优化是万恶之源”这句话奉为圭臬,以至于对任何批评或建议都充耳不闻。

    虽然在小问题上他们或许正确,但这些问题往往会累积发酵。最终,由于你多次选择不进行优化,技术选型和架构决策终将堆砌成无法挽救的臃肿烂摊子。

    比如为桌面应用选择Web框架时,安装体积、内存占用、性能下降等因素单独看或许无关紧要,但最终这些问题极易累积,导致解决方案毫无价值且糟糕透顶。对多数开发者而言,实用主义似乎是最难掌握的技能,因此无数解决方案瞬间就被过度膨胀了。

    • 太多人将“过早优化是万恶之源”这句话奉为圭臬,以至于对任何批评或建议都充耳不闻。

      确实令人沮丧,许多人竟将这句话解读为“别费心优化软件”。以下是该论文原文的上下文:

      > 程序员们耗费大量时间思考或担忧程序中非关键部分的速度,而这些效率追求在考虑调试和维护时反而产生严重负面影响。我们应当忽略97%的小幅效率提升:过早优化是万恶之源。

      > 但我们不应错失那关键3%的机会。优秀的程序员不会被这种论调蒙蔽而自满,他会明智地仔细审视关键代码——但前提是必须先识别出这些代码。

      克努特并非主张“别费心优化”,而是强调“在进行代码分析前别急着优化”。这两者有着本质区别。

      • 我老了。

        二十五年前的老板(兼导师)教导我用三步法解决问题:

        1. 先让方案运行起来

        2. 确保方案正确无误

        3. 优化方案效率

        他特别强调必须按此顺序推进。这个理念我始终奉行不渝。

        问题在于,商业压力常迫使团队跳过第三步。软件往往在第二步中途就被交付——充其量只是部分正确的半成品。

        这将问题转嫁给用户,他们可能正围绕交付代码构建系统。所有技术缺口都需填补,这加剧了软件臃肿的问题。

    • 我从未将“过早优化…”解读为“不要思考性能”,而是指在实际存在性能需求前无需实施优化机制——但设计时应始终自问“若必须提升性能该如何实现”。

      • 于我而言,这句话更强调的是:“极致优化”本身无可厚非且值得追求,但必须在需求稳定后实施(因为高度优化的代码往往难以适应新增需求)。

        任何偏离此原则的解读,在我看来都将导致臃肿低效的软件。

        • 没错——我听过类似说法:“让正常运行的东西变快比让快的东西正常运行更容易”。

    • 始终令我费解的是,为何众多开发者未能意识到:微小性能问题会持续累积——尤其当它们位于热点路径且存在依赖调用时。

      数据库领域尤甚,毕竟这是我的专业领域。“这个查询2毫秒就完成了,够快了。”好吧,但由于ORM设计得极其愚蠢,每个流程要调用它10次;若能缩短500微秒,就能节省5毫秒。或者让ORM正常工作,就能节省18毫秒,再加上每次查询忽略计算的往返时间。

    • 我曾在代码审查时对一位经验较少的开发者说过:

      > 别写 愚蠢的慢代码

      当时他们用字典做了双重查找,我鼓励他们养成只做单次查找的习惯。

      天真的人或许会说这是过早优化,但关键在于:当优化既不增加工作流程成本又能保持代码可读性时,我们应当养成选择更高效路径的习惯。

    • 我发现提及代码臃肿是让技术讨论迅速恶化的最快方式。

      我们是否需要十几个各自维护的组件(每个组件五百万行代码)来支撑热座预约页面?我不确定,但绝对不愿承受提出此疑问后引发的争论。

  6. 题外话,软件臃肿总让我思考:若工程目标不同,硬件/软件本可达到何种境界?

    若我们竭力将操作系统需求压缩到最低——是否能获得难以想象的续航提升?经年累月的超可靠技术?大幅降价的硬件?

    我们知道软件臃肿会浪费内存和CPU资源,但若开发者未将资源浪费在冗余功能上,我们永远无法知晓那些本可实现的替代方案。

    • “若我们竭力将操作系统需求压缩到最低限度——是否就能获得难以想象的电池续航提升?是否能创造经年不衰的超高可靠性技术?是否能实现硬件成本的显著降低?”

      由志愿者支持的类UNIX操作系统(如NetBSD)最符合我的理想状态

      我能够在全新硬件上运行“老式”操作系统。没有强制“升级”或远程安装的“更新”。软件升级时机由我自主决定。系统不预装任何新软件

      这让我得以观察并享受硬件升级带来的速度提升——这是企业操作系统无法实现的。后者往往会为商业目的大量占用新硬件资源,其商业目标可能与计算机所有者的非商业利益相冲突

      若软件体积不再持续膨胀该多好。即便是最简单的程序也难逃此命运。看看NetBSD的init进程随时间增长的轨迹便知

      为何不让程序缩小而非膨胀?

      正如麦克罗伊所言,那些 删除 代码的程序员或许才是真正的“英雄”(“英雄是负面编码者”)

    • 屏幕和无线电模块极大消耗着现代设备的电池寿命,即便操作系统和用户软件的运行能耗为零。

      若合理配置下电池待机仅能维持数周,实际使用最多数日,倒不如直接搭载强劲处理器——毕竟强劲处理器配合系统优化终究有其极限。这正是电子墨水设备能实现显著更长使用寿命的原因:长续航本身就是巨大卖点,因此厂商才有动力采用低功耗处理器并进行深度优化。

  7. 功能臃肿本质上反映了康威定律——开发者总在为对话对象构建系统。

    若面向所有人开发,最终会形成像Unicode或IEEE 754这样庞大的标准。这些标准中的内容未必都适用于你的消息传输或计算需求,有时甚至会与目标相悖,导致晶体管资源浪费。但它们作为默认选项足够便捷,能高效存储后续可复用的数据,因此在现代计算设备中无处不在。

    而当你针对特定计算场景——比如绘制像素或弹道轨迹的应用——你就能极致优化,精准采用所需格式和特性,从而获得紧凑的代码和高效的硬件。

    但在“模糊的中间地带”——当你试图建模信息时,系统可能采用某些标准组件却执行其他功能,业务需求不断变化,标准也在更新,而你还需要系统具备可扩展性——最终就会陷入臃肿困境。试图通过模块化拆分系统来保持灵活性,非但无法真正避免这种情况,反而会制造出“打地鼠式”的转移复杂性。使用最新工具、语言和框架也无济于事——除非它们能引导你进入能有效解决问题的标准体系。许多编程语言的行业普及往往源于某个“真正优秀的库”的出现,这本质上是一种非正式的标准化。

    面对臃肿问题时,不妨构建一张巨型可能性表格,并接受填充过程需要时间。有时能在填充过程中发现冗余并精简,但这取决于代码/文档的成熟度——缺乏经验就无法预见。

  8. TFA将可维护性列为代码膨胀的益处(“模块化、可扩展性、代码模式使维护更轻松”),却完全忽略了膨胀如何通过使代码不可知来损害可维护性。

    当堆叠足够多层——框架叠加库,库叠加抽象层,抽象层叠加依赖库——最终无人能理解系统功能。无法在脑海中完整把握,调试变成穿越17层间接调用的考古工作。功能正常运作,但无人知晓原理,更无人敢于触碰。

    原文在讨论复杂性时曾提及此点(“人们无法理解整个系统如何运作”),却将其视为独立问题。实则不然——臃肿造就不可知的系统,而不可知系统本质上就是不可维护的。

    “开发者时间比CPU周期更宝贵”的论点在此彻底崩塌。你并非节省时间,而是转移成本。引入框架“节省”的工时?每当有人调试跨越六层抽象的未知问题时,你都要连本带利地偿还。

    • 高度优化的程序往往源于对问题领域的深刻理解、良好的范围划分和专注的思维。

      在我看来,我们已深陷框架泥潭——框架往往制造泄漏的抽象。人们常误以为框架能节省时间、简化流程、卸载复杂性。但使用框架意味着必须让程序适应其抽象体系。这种承诺极其复杂,蕴含深远影响,一旦形成便难以逆转。

      许多框架都能被用来解决任何问题,这反而使情况更糟。它助长了“手里只有锤子,看什么都像钉子”的思维定式。通往解决方案的捷径不再是直线,而是通过念诵特定咒语引导框架走向目标——这必然导致方案变得更抽象、更复杂且效率更低。

    • > 当堆叠足够多层——框架叠加库,抽象层叠加依赖层——最终无人能理解系统如何运作。

      这种推理站不住脚,因为所谓“优化”实现往往依赖性能黑客手段,导致代码完全不可读。

      > 原文在讨论复杂性时提及此点(“人们无法理解整个系统如何运作”)。但将其视为独立问题。实则不然。臃肿本身就催生了不可知的系统。

      我认为你混淆了概念。臃肿与缺乏清晰的软件架构并非同一回事。基于低级GUI框架(如Win32 API)开发的普通应用,往往比基于高级框架(包括Electron应用)构建的同类应用更复杂难维护。若将应用开发成一团乱麻,无论使用何种框架(或不使用框架),你都将陷入理解困境。

      • 我并非提倡不可读的优化黑客手段。我是在TFA的框架体系内展开讨论。TFA认为某些膨胀(框架、层级、抽象)是合理的,因为它们通过“模块化、可扩展性、代码模式”提升了可维护性。

        我的观点是:这些层级本身会引发TFA忽略的另一类可维护性问题。当你将框架、库、抽象层层堆叠时,就会形成无人能全盘掌握的系统。这才是真正的代价。

        即使采用洁净架构仍会遭遇此问题。精心设计的17层系统,依然存在17层间接关系横亘于“用户点击按钮”与“数据库更新”之间。

      • > 此为谬论,所谓“优化”实现往往依赖性能黑客手段,导致代码完全不可读。

        这完全取决于具体情境,而你基于不成立的假设进行泛化:

        用手工编写的SQL替换臃肿的ORM代码,若最终生成的是简单查询且查询结果能与对象完美映射,确实可能大幅提升可读性。但同样可能演变成极其复杂、难以追踪的查询,需要进行高难度操作才能填充对象图。

        优化CPU使用率的情况亦然。可能是去除了不必要的复杂性,也可能是需要展开循环和复制粘贴代码的微优化。

        我必须指出自己亲身经历过ORM问题:曾将某产品中的ORM移除后,其性能跃居行业领先,代码也变得极其简洁,新员工甚至称赞数据访问逻辑清晰易懂。反观我当前负责的产品,则恰恰是ORM存在的合理例证。

        我也经历过CPU占用率问题:曾不得不重构将数值时间戳转为字符串的代码,随后又出现复杂的字符串解析逻辑来处理时间戳运算。重构方案是用定义类型替换字符串,不仅速度提升,代码也更易理解——时间戳实现了良好封装。

    • 我的意思是,代码膨胀存在不同类型。有些是合理的,有些则不然,还有些只是其他问题的症状(后两者并非互斥),比如管理失当、能力不足(来自管理层、开发者、团队负责人等)。这有点像胆固醇,存在不同类型的胆固醇,有些可能非常有害,有些则可能无害等等。

      代码膨胀(此处指代码重复?)既可能是可维护性问题的根源,也可能是其表现症状。这如同恶性循环。意大利面式代码混乱(与代码膨胀不同)往往会导致后续膨胀,因为开发者根本不清楚自己在做什么——此处指消极意义上的混乱。即便对整个系统不熟悉,只要代码组织良好、具备可复用性、模块化且可测试,开发者仍能相对顺畅地工作,且不必担心引入严重回归(如面对意大利面代码时)。重构操作也会轻松许多。反之,管理不善的意大利面代码极难测试与复用。开发者面对此类代码时,往往不愿复用现有代码——因其本就脆弱不堪且无法复用。每开发新功能时,他们宁愿创建或复制新函数。

      这形成恶性循环:代码开始腐化,日益难以维护,充斥着冗余、脆弱且极可能低效的代码。这正是我所指的状况。

  9. 极端臃肿化令我困扰的一点在于:我不希望每个应用都逼近计算机的处理极限。某些游戏、编译器或复杂软件偶尔触及极限尚可接受。支持臃肿化的常见论点是软件应充分利用硬件资源而非闲置,这种观点在某些场景下有道理。但99%的情况下,我更倾向于使用体积小巧的软件——这样我能拥有 大量 副本,永远不必担心磁盘或内存占用。

  10. 这篇文章关于合理膨胀的论点基本正确,但“过早优化是邪恶的”已沦为彻底放弃效率思考的借口。当我们为简单应用选择Electron框架,或为基础任务引入200个依赖项时,这并非务实,而是制造了复杂性债务——其调试耗时往往远超编写精简代码所需。但现实就是如此,所以…

    • 思考本就艰难,因此任何能让人停止思考的产品都会大受欢迎——即便它制造了框架臃肿、依赖腐化等更多麻烦。这正是将AI硬塞进所有领域如此成功的根源:它给了人们停止思考的许可。

    • 没错。太多人似乎遗忘了“过早”这个词。这句话已被严重滥用,用来为最恶劣的臃肿和未优化软件开脱。

      • 是啊,不知怎的就从“别对循环做微优化”变成了“500MB的Electron应用其实完全没问题哈哈哈”

        • MacOS上最新MS Teams更新的安装程序居然要求1.2GB(没错,是GB!)磁盘空间…

          • 最近发现Teams在我的笔记本上占用了超过5GB空间。微软开发者的无能真是无止境。

          • 最近虚拟机无法打开时,我用Xubuntu搭建了新虚拟环境。

            结果发现现代Ubuntu只支持通过snap安装Firefox。而snap会毫无理由地自动膨胀占满整个硬盘。

            实在不明白当初是谁认定这种包管理方案合理。

        • 希望Tauri能获得更多关注(https://v2.tauri.app/)。其最大优势在于显著缩小的构建体积(https://www.levminer.com/blog/tauri-vs-electron)。

          一个500MB的Electron应用,用Tauri实现后轻松缩减至20MB。

          • 不太确定。Tauri应用在浏览器中运行,而浏览器是绝对的内存占用大户。我的浏览器始终是滥用可用内存的头号元凶——看看它启动的进程数量就够疯狂的了。我试过所有主流浏览器,它们都是内存消耗怪兽。

            • Tauri规避了Electron的一个主要缺陷:它避免将特定浏览器打包到应用中,从而避免了每个Electron应用安装包因Chromium体积而膨胀的问题。虽然打包NodeJS(或Tauri的等效后端)也会增加体积,但差异主要在于后端选择而非是否包含后端本身。

              无论哪种方案,最终都会生成独立于日常浏览器的全新浏览器实例(除非Tauri近期有所改动),因此两者在内存占用层面并无本质差异。因此你说的没错,这是两种方案共有的问题。但根据我的经验,非开发人员更在意包体积而非交互式内存占用。Tauri应用冷启动速度可能更快,因为它加载的是全新的浏览器实例——每个字节都需要从磁盘读取。我认为普通用户更关注的是启动速度而非内存占用。

              曾有几个项目试图成为Electron的替代方案,它们完整包含NodeJS,但像Tauri那样使用用户当前安装的默认浏览器;还有些项目则用更轻量级的后端替代Electron,更接近Tauri的模式。但这些项目大多目前处于无人维护状态,仍处于官方alpha阶段,或是存在功能不完整/运行不稳定/兼具两者的问题。Electron具备三大优势:存在感强、稳定维护、性能足够出色(除非出现重大缺陷——一旦出现缺陷,用户往往会转向完全不同的替代方案而非类似系统)。当用户逃离Electron时,通常会选择截然不同的替代方案,这使得新兴类似项目难以与Electron的既有势头竞争。

            • 根据https://v2.tauri.app/concept/architecture/所述,Tauri采用原生WebView技术,这使得Tauri应用比基于Electron并运行完整浏览器的工具更轻量且更节省内存。

            • Electron应用同样在浏览器中运行,它们将整个浏览器打包为应用的一部分。

        • 因此“你需要32GB内存才能确保未来三年不被淘汰”。

    • 所幸许多应用似乎正转向原生WebView,而非继续使用Electron

    • 讨论中常忽略产品预期生命周期。若只是概念验证或用户稀少的应用,用Electron开发简单程序或许合理。但若将其用于操作系统内置计算器,权衡取舍就截然不同了。

      • 绝大多数Electron垃圾应用本可转化为常规网站,但开发者必须真正面向Web而非ChromeOS平台——显然这难度太大。

        • 最近我重新深入(但仍保持独立)从事基于Vue.js和Quasar的Web开发,说实话我甚至不再考虑“针对Web平台”的问题——我只需编写代码,它似乎就能在绝大多数环境下运行(公平起见,我尚未测试Safari)。

          • Vue实在太棒了!最近看到越来越多机构在招聘帖等场合提及使用它,这让我倍感鼓舞。

    • 我认为高速应用/API的极端复杂性正迫使许多开发者转向超慢但易用的应用/API。我们需要找到中间地带——既易于使用又足够快速的解决方案,而非在牺牲可用性的前提下追求极致性能。

      • Java Swing?1999年它很慢,现在反而快了。而且Java比JavaScript合理得多。它虽非原生GUI,但JavaScript同样不是。

    • 可悲的现实是:简单技术能更快探索解决方案空间

    • 反过来说,这种论调也常被滥用作借口——既贬低Web应用,又推崇其他可能更糟糕的替代方案。

      我从未见过真实世界中用户量庞大的Electron应用存在大量依赖或性能问题,这些问题通过原生开发就能解决。许多开发者竟未意识到并发HTTP请求会带来多少延迟和内存消耗,这令我费解。若有反例,我非常乐意一睹为快。

  11. Web服务的性能主要取决于调用次数及调用外部服务的响应速度。若系统本可通过单次调用实现的功能却进行了两次数据库调用,这理应成为优化的首要目标。

    事实上,即使某种语言或框架的代码执行效率较低,但若能支持高效查询,整体性能仍可保持相对良好。

  12. > 这种臃肿现象很大程度上实为权衡取舍

    或者根本不是,这份清单也未能超越“用户资源更丰富,所以更容易浪费资源”的论调

    > 层级与框架

    这类组件多如牛毛,性能差异达数量级之差。因此空泛的引用无法解释膨胀问题

    但同样

    > 本地化、输入法、矢量图标、主题支持、高DPI适配

    若能让用户清晰阅读应用文本!或避免画面模糊!或消除“刺眼”问题——这就不算膨胀!

    > 健壮性与错误处理/报告

    同理,你指的是洗衣机每天发送数千兆数据却毫无“健壮性提升”?还是指某种具备完美时间回溯/重现能力的虚拟化开发环境?在这种环境里,任何硬件“臃肿”都不会影响用户体验。过去的错误处理与现在相比,除了能轻松发送崩溃转储文件外,实际有何不同?

    > 工程权衡。我们接受更高的基准门槛,以实现跨多设备更快、更安全的代码交付。

    但我们绝不这样做!代码往往运行缓慢,恰恰是因为人们总准备着这类空洞的陈词滥调:

    > 硬件性能提升了三个数量级。开发者时间往往比内存或CPU周期更宝贵

    那用户的时间/资源价值呢?为何要忽视这种简单二分法之外的现实?还是说开发者根本无从知晓用户的痛苦?毕竟所谓的“健壮错误处理与报告机制”根本名不副实,它不过是将大量用户体验直接丢进/dev/null垃圾桶罢了?

  13. 文中提及诸多权衡取舍。问题在于,这些权衡往往是为支撑系统臃肿而存在的——臃肿需要臃肿来维系。

    – 层级与框架:我们始终存在某些层级与框架,最大的当属操作系统。问题在于,如今应用程序不再共享这些层级(共享库、操作系统调用等),而是各自为政,各自搭载专属框架。以计算器为例,字体、通用控件、渲染代码等皆然。即便在早期,全局占用空间可能已达数MB,但其中绝大部分与其他应用及操作系统外壳共享,因此计算器实际仅需额外几KB空间。

    – 安全与隔离:这主要由操作系统甚至硬件负责。但我们如此重视安全的核心原因在于:代码越臃肿,漏洞滋生的空间就越大。本就不存在的组件自然无需隔离。

    – 健壮性与错误处理/报告:代码越精简,出错概率越低,系统更稳健且需处理的错误更少。

    – 国际化与无障碍支持:确实会增加冗余,但这本应由操作系统承担。若全行业采用统一的共享GUI工具包,这些问题只需由该工具包统一处理。需注意,Windows 9x时代已解决其中多数问题。

    – 容器与虚拟化:容器化是解决依赖地狱与非可移植代码的方案,它让你随身携带完整运行环境,无需适应新环境。依赖项越多(即系统越臃肿),容器化需求就越迫切。但涉及安全性和可访问性时,由于环境随应用打包分发,系统级更新带来的安全修复将无法惠及这些应用。

    – 工程权衡:计算机硬件廉价,开发人力昂贵。我们实际上是在用手工打造轻量化优化软件的时间,来换取应对系统臃肿的代价。

    我理解作者观点,但认为其中大部分是自找的。记得安卓早期,我用Nexus One(512MB内存/1GHz单核CPU/512MB闪存+4GB MicroSD)就能完成现在手机的绝大多数功能——而现在手机在每个方面都强十倍以上。这还是在支持国际化、进程隔离、JVM等复杂架构的前提下实现的。更何况当时谷歌规模远小于如今,所谓降低开发成本不过是空谈。

  14. 我在企业级B2C软件领域工作,主要涉及单页应用/自助服务门户等项目。我不认为我们的软件本身臃肿;当然速度可以更快,但以移动应用为例,这涉及多重权衡:追求最佳体验与速度、招聘人才、开发效率以及非功能性需求。

    现有方案已足够优秀。比如React Native耗费数年和数百万资金进行深度优化,只为让“足够好”变得更快——他们的工作远超我的能力范畴。(https://reactnative.dev/blog/2025/10/08/react-native-0.82#ex…)

    • 就内部服务而言,我同意能轻松添加功能是首要任务。

      对于面向客户的系统,我认为值得研究支持后端模板化的框架,再通过轻量级DOM操作实现客户端动态效果。像Phoenix这样的框架能让操作变得非常高效。

      这是值得掌握的实用工具。

    • 95%的门户网站用2000年代的技术就能实现(毕竟本质上是CRUD应用)——关键在于这样做是否值得。

      答案几乎总是“毫无价值”,因为“够用就好”就足够了。

      人们总爱贬低Electron这类开发工具,但现实是:若应用在Electron上表现糟糕,用原生代码实现时同样糟糕——因为我们完全能编写优质的Electron应用。

      • > 但现实是:若应用在Electron上表现糟糕,用原生代码实现时同样糟糕

        仅启动速度就能明显提升,应用体积可直接缩减数百MB,所以绝不会同样糟糕。

        > 因为完全可以编写优质的Electron应用

        关键问题在于实现难度,而非可能性本身。

      • 每当想到优秀的Electron应用,Visual Studio Code总会第一时间浮现在我脑海。开发者们确实付出了巨大努力,让这款编辑器既能保持响应灵敏,又能实现复杂功能,同时不会耗尽你的内存/磁盘预算。

        但相比我使用的Emacs编辑器,它依然显得臃肿。

        与功能相当的Java平台IDE相比,它依然显得臃肿。(Eclipse和IntelliJ的开箱即用功能远超VS Code。)

  15. 点击页面某些内容时,会被重定向到垃圾Opera下载页面

    • 我想这就是网站所说的“可接受的软件臃肿”吧 🙂 (我没点。先看评论确认是否值得点击。)

      • 哈哈。这现象类似恶意Chrome插件的作案手法——页面链接会随机在新标签页加载垃圾网站,但后续链接就能正常使用。我确定不是我安装的插件搞的鬼。

  16. 臃肿永远是坏事。

    话虽如此,工程设计本质就是权衡取舍——接受部分弊端以换取相应收益。

    但当下企业似乎甘愿为微薄甚至虚无的回报接受臃肿,这正是我认为如今大量软件质量低劣的原因之一。

  17. 这篇文章太棒了——我超爱这个梗

    作为三十年前主修计算机科学、后转入IT行业的第一代从业者,我一直困惑于代码膨胀问题,这篇文章给了我通俗易懂的解释。

    最震撼的是那个对比:超级马里奥的WEBP图片竟比游戏本体还要大!

    • 马里奥图片极具误导性。它并非无损格式,色彩数量严重超标。真正的无损截图(虽宽度不足)仅3KB:

      https://en.wikipedia.org/wiki/File:NES_Super_Mario_Bros.png

      • 抱歉,是我疏忽了。看来文件大小对压缩方式和软件的选择也极为敏感(无论采用PNG还是WEBP格式)。我在这里找到另一张PNG图片https://www.freecodecamp.org/news/where-do-all-the-bytes-com…,大小为64KiB。当你拉伸图片时,也可能增加数千字节。我猜我需要更新图片。

        但无论如何,当整个游戏体积比其图片还小时,这仍然具有很强的示范意义。再想想,即使你那个微小的PNG示例(3.37KiB)仍无法装入NES主机的RAM/VRAM,这凸显了不同时代在内存容量上的巨大差异。

        • > 我在此处发现另一张PNG图片

          该图片存在与您类似的问题。它通过某种插值方式放大后,为平滑边缘引入了大量额外颜色。这种处理方式并不适合PNG格式,因此文件体积达到64KB。

          文章宣称其仅有5.9KB。我推测原始文件确实如此小巧,但在发布过程中遭到破坏。

          • 我认为更合理的对比对象是BMP图像(16色或256色),因为游戏并未像PNG或WebP那样对图像进行压缩。当我将那张约3KiB的小图转换为16色BMP时,文件量增至28.1KiB;转换为256色时更是达到57KiB。不过部分色彩确实丢失了。

            总之我认为无法进行百分百的同等比较,因为游戏采用了不同的压缩和渲染技术。还需考虑图像实际占用的内存/显存空间。在内存/显存中,它们很可能以解压缩形式存在,占用空间更大。

  18. 有时膨胀是强加于你的。

    最近我不得不编写安卓应用。我讨厌冗余代码,所以禁用了所有库。虽然成功了,但过程充满障碍。Android开发默认依赖appcompat等库。最终我的APK仅30KB,却能在所有目标机型(从Android 8到16)运行。而Android Studio的Hello World APK约2MB——这简直疯狂。

    • 究其根源,Android曾大肆宣扬其相较J2ME碎片化的优势——这种营销手段仅能迷惑缺乏经验者。事实证明,大量appcompat代码实则是为应对不同OEM厂商和设备间的Android碎片化问题。

    • 约十年前(在被谷歌禁止发布Android应用前),我曾发布过一款Android应用,当时情况正是如此。每次打开Eclipse,它都会自动向原本仅50KB的应用添加6MB的“支持库”。无法关闭此功能,但若手动移除,该设置仅在当前会话有效。通常直到构建最终.apk文件准备上传应用商店时,我才发现自己忘了移除它。

  19. 当替代方案更糟时,膨胀是可以接受的。但你是否真正分析过膨胀会变得多糟、多严重?不过如果替代方案更糟,膨胀依然合理。

  20. 有时我觉得React对世界最大的贡献并非加速前端开发之类,而是揭示了多少关于性能的讨论纯属多疑。

  21. 或许有些情况如此,但我们早已超越了“可以接受”的阶段。

  22. 我很好奇,能否通过代码组装实现性能飞跃?或许现有AI尚未充分训练这方面能力…但理论上无需大量工作就能获得惊人性能?…唯一缺点是完全无法理解代码原理,且将彻底失去可维护性。

    • 我正用它做些Z80/6502/x86_64汇编开发,还用sdcc和gcc写点C代码。比想象中更有趣。

  23. 遗憾的是,这篇文章对所有非大都市居民极具冒犯性——它假设我们除了每日享用蛋糕外,无限流量及获取途径不过是微不足道的琐事(即便提及也如此轻描淡写)。农村地区正加速衰败,另一篇报道描述了加州乡村电力供应的极不稳定性。我暂不赘述细节,但请想象这样的场景:当你身处地球绝大多数区域的现实——电力可能永远不会恢复时,不得不尝试关闭运行超低速带宽网络的Win11笔记本以节省电量,这该是何等“乐趣”。

  24. > 感谢微软滥用GitHub垄断地位,实施窃取数十亿行GPL代码的法律争议行为

    这算谬论吧?

    但真有人信这套就太荒谬了。

    开源代码不可能被“窃取”。GPL与自由软件运动的核心宗旨正是保障软件的自由使用与修改权。

    • 开源代码绝对可能被窃取——只要其使用方式违反共享协议条款。以GPL为例,这意味着必须向用户授予与你相同的自由权限,而据我所知,“Open”AI公司显然完全未履行此义务。

  25. 我想测试Electron应用与同等原生应用相比,究竟会消耗多少电脑电量。之后我们再讨论臃肿是否合理。

    附:有人知道谁做过这类测试吗?

    • 你都用过Electron了,还需要基准测试来证明它臃肿?

      • 我早就知道它臃肿!我就是要用数据证明它对日常使用造成多大影响。

  26. 若能制定一条软件相关法律,我定要禁止React及类似框架(包括Vue和Svelte):凡需在JavaScript中嵌入多行HTML、采用虚拟渲染树(VDOM)、或涉及构建步骤者——皆应列为非法。完全可以编写一种从顶层挂载到 DOM 的 JavaScript 框架,无需任何昂贵的 hydration 步骤、虚拟渲染或模板机制(我亲手实现过)。React 是个可怕的复杂怪物,既浪费开发者时间,又让用户 CPU 发烫,整体体验极其迟缓卡顿。99%的网站采用服务器端渲染(SSR)配合少量JavaScript代码就能运行得更好,根本无需引入React这类框架。React堪称软件史上最糟糕的发明。

    • > React及类似框架(包括Vue和Svelte)

      把React和那两个框架相提并论简直是 天方夜谭

      > 99%的网站采用服务器端渲染加少量JavaScript就能运行得更好,根本没必要引入React这类框架。

      或许如此,但页面稍带逻辑时,Web基础组件就变得难以驾驭。

      况且我必须能在1%的领域有所建树。我确实做过:用Vue构建了完全客户端的应用,以单个HTML文件形式分发实现“无服务器”特性。虽然最近几个月已改为部署在正规服务器上。

      不过某些后端开发者承受的心理创伤程度实在令人捧腹。我理解软件很糟糕,这很悲哀,但没必要搞得那么夸张。

      顺便说一句,关于禁止使用某些东西:没有任何库、进程或方法能替代真正理解你在做什么。

      • 你完全可以实现非常复杂的功能,而无需采用类似React的方案。我明确表示自己编写过一个极其高效的复杂框架——这才是适用于那1%场景的解决方案(指方法论而非具体框架)。更妙的是,我能通过渐进式部署策略在不同服务器端渲染页面中引入该方案,随后(若需要)将整个应用转为单页应用——全程无需借助JavaScript、虚拟渲染树或其他类似的无用技术进行“渲染”。

        • 这个框架公开了吗?我与你理念一致,也开发了包含/不含你提及功能的框架,希望能对比我们的方案。最大区别在于我采用lit-html进行模板渲染,效率相当高。

    • > 完全可以编写一种JS框架,它从顶层挂载到DOM上,无需任何昂贵的hydration步骤、虚拟DOM或模板引擎(我已实现过)

      能否详细说明实现原理?是指JS将服务器生成的HTML加载到DOM中吗?

      • 服务器渲染页面。假设页面中有如下元素:<div data-component=“HenloComponent”>...</div>。随后加载到该页面的.js框架会查询DOM中所有带有data-component属性的元素,并创建HenloComponent实例(该组件是你作为框架开发者编写的类)。实际过程稍复杂些,但核心原理如此。

        需注意此方法无需额外“渲染”操作——浏览器已完成渲染,你只需通过组件实例为DOM元素附加功能。

        • 是的,这正是我所询问的内容。

          我完全赞同。当不得不这样做时,我也是这么操作的——尽管作为后端开发者,我主要处理简单的JS逻辑。若涉及前端工作,通常只是“HTML加少量JS”,通过ID将内容加载到div中。

          和做 React 的前端开发者合作简直是噩梦。最糟糕的情况是他们用 Next.js 写了个第二后端,夹在我现有的 Django 后端(早先完成的)和前端之间。延迟简直绝了!虽然是极端案例,但彻底让我对复杂前端失去兴趣。项目最终流产。

          • > 最糟糕的情况是他们用Next.js写了个第二后端,夹在我现有的Django后端(早先完成的)和前端之间。

            这太搞笑了。

            Casey Muratori确实说得对:在优化软件前,要先做到“非悲观化”(即让软件完成应尽之责,而非过度设计)。

          • 天哪,他们真这么干?我还以为Next.js本身就是像Django那样功能完整的后端框架。没想到它竟只是个中间人后端,负责渲染从其他后端获取的模板。

            • Next.js确实是功能完整的后端框架。这并非Next的过错——我讨厌它另有原因,但这绝非Next的问题。

              症结在于相关前端开发者决定用Next.js替换一个基本完工的Django网站前端。这显然是典型的“只愿用熟悉工具”的思维定式,完全不顾适配性——正如“手里只有锤子,看什么都像钉子”的谚语所言。

              • Vercel确实有“责任”,因为它将Next.js包装成BFF(后端为前端)解决方案——这个概念原本并不存在,却助其售出大量React托管服务,这完全出乎所有老派React开发者的意料。

    • 何不干脆抛弃HTML本身?反正人们每天都在下载二进制文件,不如直接下载某个二进制程序,在隔离环境中执行。这样就只需传输数据了。

      • 我认为HTML本身没问题。它易学易用,是绝佳的网页格式。CSS同样出色,JavaScript也相当优秀。我的观点是:现代网页之所以糟糕,是因为那些既无品味又不懂底层技术的人,通过发明颠覆网页本质的框架,将其变成臃肿不堪的垃圾秀。我生活中很少憎恶事物,但对此却充满激情——每次访问网站时,那种迟滞卡顿的体验让我立刻能辨认出这是React框架的杰作。

      • 不知你有多认真,但我认为核心理念是:内容应由HTML承载,应用程序则纯粹用JS实现。

        更进一步,我们可以设计专属沙盒虚拟机运行的语言,搭配为该任务定制的GUI库,而非从文档格式衍生而来。

        • 是的,我觉得我的观点被误解了:我反对的部分内容是将HTML(更糟的是CSS)写在.js文件里。

          • 没错,我觉得你确实被误解了。

            我认为JS里嵌HTML是代码异味。至于为什么要在JS里放CSS,我简直无法想象。

      • 呃,你见过如今所谓“原生应用”里那些花哨的UI实现方式吗?任何比按钮、标签等1993年就存在的元素更复杂的功能,都会被塞进WebView里用HTML和CSS渲染。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注


京ICP备12002735号