前端框架的繁荣史,本质上是一部“抽象膨胀史”。从jQuery的DOM便捷操作,到React的组件化模型,再到Vue的响应式数据绑定,以及Svelte的编译时魔法——每一次迭代都试图解决先前的问题,却也同时引入了新的复杂度层级。开发者开始需要理解virtual DOM的diff算法、fiber架构的优先级调度、依赖收集的触发时机、甚至编译器对模板的优化策略。而这仅仅是框架本身的复杂度,尚未包括围绕框架诞生的路由、状态管理、构建工具、代码分割等附属生态。当我们环顾四周,发现一个React项目竟然需要引入十几个依赖才能“优雅”地启动时,我们不得不承认:前端框架正在经历一种不可逆的“熵增”——复杂度自发增长,而开发者则被迫不断适应这种增长,并将其视为“技术演进”的必然代价。
我所谓“框架熵增”,是指框架在发展和迭代过程中,其内部结构和抽象层数越来越多,导致学习和维护成本呈指数级上升,而实际为用户体验带来的边际收益却急剧递减。以React为例,从class组件到hooks,再到server components与concurrent模式的引入,框架本身实现了惊人的“能力”扩张,但普通开发者的心智负担也在同步加重。甚至可以说,React的每一次版本升级,都是对社区“记忆成本”的一次敲诈——你必须理解新的调度机制、新的缓存策略、新的并发模型,否则就无法写出“最佳实践”。Vue似乎温和一些,但当你深入模板渲染优化的细节,不得不掌握其diff算法中的具体flag标记、动态节点追踪等知识时,你同样会感知到那层无形的熵墙。这并非任何一家公司的“罪过”,而是整个软件工程演进的惯性——当系统无法自我简化时,就会自然生长出更多补偿机制,而这些补偿机制又成为新的负担。
面对这种熵增,各主流框架给出了不同方向的反制方案,但这些方案都仍然停留在“优化框架自身”的维度,而非跳出框架看问题。React选择在运行时做极致的“可中断渲染”与“优先级调和”,这是运算层面的降维;Vue选择在编译期做静态标记树,让运行时的diff范围大幅缩减,这是优化层面的降维;Svelte干脆取消virtual DOM,将组件代码直接编译为原生DOM操作,这是结构层面的降维。然而,这些所谓的“降维”归根到底都还是一种“对抗”——对抗浏览器DOM的性能瓶颈,对抗JavaScript单线程的渲染延迟,对抗状态同步的繁琐。我从这些变化中看到了一条更本质的降维路径:让框架自动化的不是“DOM操作”或“渲染调度”,而是“数据”。Signal正在向这个方向靠近,它不再关心组件如何重渲染,而是将状态本身视为一种有生命力的“原子”单位,精确地知道谁在依赖它、何时该更新。这才是真正的范式转移——并非让框架做更聪明的事,而是让框架放弃做那些不必要的事。
然而,当前的生态里还充斥着“为解耦而解耦”、“为复刻而复刻”的恶性竞争。不少团队以“学习周期”“招聘难度”为由彻底推翻现有架构,投入另一个庞大框架的怀抱,结果只是换了另一种形式的熵增。我提出一个非常独立且反主流的原则:“最小框架”原则。这个原则并非主张消灭框架,而是要求任何框架在设计、使用和演进过程中,始终评估“如果不这样做,系统的复杂度会更低吗?”——所有可有可无的抽象层、所有只是为了避免一次全量更新的性能优化、所有为了迎合某些“极端业务场景”而设计的通用型API,都应该被无情地移除或隐藏。一个好的框架,应该像数学里的“公理”,而不是像百科词典里的“词条”。开发者应当被引导去思考业务逻辑本身,而不是日夜纠结于“useMemo应该怎么依赖”、“watch与computed到底谁更快”。在这个意义上,我认同Svelte的激进——它确实用编译器把繁琐的运行时简化成了最直观的JavaScript语法;我也欣赏Solid的“信号”模型——它让状态与视图之间的关系变成了一种近乎物理定律的确定性关联,而非框架内部的“黑魔法”。
最后,我要说,前端框架的终点不会是另一个框架。它会逐步演化为一套“编译器 + 运行时最小化 + 心智模型简化规范”的复合体,甚至最终与标准浏览器API融为一体。想一想历史:jQuery的链式选择器最终成了querySelector;Backbone的集合模型最终被原生数组和fetch取代;Bootstrap的组件样式最终被标准化进了CSS Grid和Flexbox。今天这些看似强大的框架,同样会被时间冲刷,留下的是那个更简、更普适的“理念”——比如响应式数据、组件化思维、声明式UI。而这些理念最终会内化为浏览器平台自身的能力,到那时,我们不再需要安装几十MB的node_modules,不再需要维护一份不断膨胀的lock文件。我希望前端开发者都能拥有一种“观察者视角”,跳出于当前纷繁的框架之争,去审视真正的目标:让构建应用变成一种“接近思考本身”的行为,而不是一场与工具链拔河的持久战。这才是我们应孜孜以求的未来,也是“降维”的终极意义。