2020年他还在写React、配webpack、调source map。现在他只用原生JavaScript(Vanilla JS)和浏览器接口直接写项目,且"再也不想回去了"。
这个转变不是情怀驱动,是一次deadline逼出来的意外发现——而那次发现让他质疑:整个前端行业是不是集体陷入了某种"框架依赖症"?
被 deadline 逼出来的"叛逆"
作者原本是桌面端商业应用开发者,入行前端时单页应用(SPA)框架已是主流。他的第一次"出轨"纯属被迫:某个项目 deadline 太紧,根本没时间把关键库接入 React 生态。
于是他直接操作 DOM,手写了一个约 50 行代码的流对象来响应用户输入。结果"运行完美"。
他的原话是:"我感觉被骗了。我以为让网页交互是只有 SPA 框架作者才能完成的疯狂困难任务?结果我就……直接写脚本而已。"
今年他又遇到类似场景:需要为确定性模拟测试(Deterministic Simulation Testing)项目生成一个 HTML 报告。离开前端一段时间后,他本能地遵循"最佳实践"选了 Preact,却不断遇到"水合错误(Hydration errors)"和"组件树"相关的报错。
他不仅忘了这些概念什么意思,更重要的是——"我也不再在乎了"。
回头改用原生方案,"又一次……没问题。甚至更好了。"
"原生"这个词本身就很荒谬
作者特意吐槽了行业术语的荒诞。"原生 JavaScript"和"原生 CSS"这种说法让他困惑:"我又不是在小型计算机前面板上拨开关输入十六进制代码,我是在用带垃圾回收、闭包和原型链的脚本语言操作交互式文档。"
换句话说,现代浏览器接口本身就是高度抽象的成熟平台,不是需要"框架拯救"的原始荒地。
React 被营销为"DOM 之上的抽象层",技术上没错,但 spirit(精神实质)上并非如此。React 的抽象方式、组件模型、状态管理、构建工具链——这些才是开发者真正要学习和维护的复杂层。而它们与浏览器实际运行机制之间的映射,越来越像一层需要持续翻译的方言。
维护成本:被低估的复利杀手
作者的核心论点指向一个被行业长期回避的问题:技术债务的复利效应。
浏览器接口的改进是渐进且向后兼容的。一个 2015 年写的原生 DOM 操作脚本,今天大概率还能跑。但 React 15 的项目升到 React 19?你需要重写生命周期、迁移 hooks、更新构建工具、处理废弃 API。
框架的"快速迭代"对短期项目可能是优势,对需要维护数年的生产代码则是风险敞口。作者称之为"all in on a single, rapidly moving JS framework"——把筹码押在单一、高速移动的目标上。
更隐蔽的成本在文档和调试。原生 JavaScript 的文档质量"极佳",不仅对人友好,对大型语言模型(LLM)也友好。当你让 AI 生成代码时,基于标准接口的上下文比框架特定模式更稳定、更少幻觉。
而 source map、transpiler、bundler 的消失,直接消灭了前端开发中最令人头疼的调试体验——"终于可以直接按浏览器设计的方式写网页了。"
开发者体验:做减法反而更自由
作者描述的体验转变很具体:没有构建步骤的等待,没有 hydration 错误的排查,没有"这个 state 为什么没更新"的深夜调试。
这种"减法自由"与行业主流叙事形成反差。过去十年,前端工具链的复杂度持续膨胀,从 grunt 到 webpack 到 vite,从 class 组件到 hooks 到 server components——每一步都承诺"更好的开发体验",但累积结果是认知负荷的指数增长。
原生方案的"简陋"反而成为一种保护:你面对的问题域被限制在浏览器实际提供的接口内,而不是框架抽象层与浏览器行为之间的缝隙地带。
作者两次"被迫"使用原生方案,两次都发现"更简单、更直接、足够好"。这个重复模式暗示:很多项目根本不需要框架提供的全部能力,却承担了框架的全部成本。
谁该认真考虑这个选择?
作者明确限定了适用范围:任何"将在生产环境运行超过几个月"的项目。短期原型、快速验证的场景,框架的脚手架价值仍然存在。
但他的观察指向一个更尖锐的问题:行业默认的"最佳实践"是否过度预设了项目规模?很多内部工具、数据报表、管理后台,本质上是一个"带交互的文档",却被套上了完整的 React/Vue 工程体系。
这种"过度工程化"的惯性,部分源于人才市场的信号机制(简历需要框架关键词),部分源于教育资源的倾斜(教程默认从框架开始),部分源于对"可维护性"的误读——把"团队熟悉度"等同于"长期可维护性",忽视了框架版本迁移的实际成本。
原生方案的可维护性建立在更稳定的地基上:浏览器标准。这个地基的移动速度以年为单位,且承诺向后兼容。框架的移动速度以月为单位,且经常需要破坏性升级。
一个被忽视的中间地带
文章最有价值的部分,可能是对"非黑即白"思维的打破。
作者不是反对所有抽象,而是质疑特定类型的抽象——那些与平台行为错位、需要持续同步的抽象。他两次成功的原生实践,都保留了适度的自建抽象(50 行的流对象),只是这些抽象完全基于浏览器接口,没有跨层的翻译成本。
这种"轻量抽象"模式,与近年来部分框架的演进方向暗合:Alpine.js、Petite Vue、甚至 React 的"服务端组件"都在尝试减少客户端运行时的重量。但作者的选择更激进:直接去掉框架层,只在必要时手写最小化的辅助代码。
这个模式的成本是前期设计负担——你需要自己决定状态如何流转、DOM 何时更新。框架的隐性价值正是替你做这些决定。但当这些决定与项目实际需求不匹配时,框架就变成了约束而非助力。
作者的两次经历都发生在"时间压力+功能明确"的场景,这种约束反而帮助他做出了更贴合实际的选择。没有"最佳实践"的心理负担,没有"团队会怎么看"的政治考量,只有"这个需要跑起来"的单一目标。
结果证明,浏览器平台本身已经足够。
如果明天你要启动一个预计维护两年的内部工具,你会默认打开 `npm create vite@latest`,还是先问自己:这个功能真的需要框架吗?
热门跟贴