
2025年的最后几天,当你回顾这一年的前端技术发展,是否感觉到了某种微妙的变化?
从一次版本升级说起
上周接到一个需求,听起来简单到令人发笑:把UI组件库从2.7.1升级到2.7.3。
两个patch版本的差距,按理说跑个npm update就完事了。但现实是什么?技术Leader给我的排期是三天。
你没看错,三天。
为什么?因为这个看似简单的升级会触发一连串的连锁反应:
go
升级组件库 2.7.1 → 2.7.3
↓
引发依赖冲突
↓
需要升级另外3个依赖包
↓
导致组件导入方式变更
↓
需要重构200+个组件引用
↓
单元测试全部失败
↓
需要重写测试用例
↓
CI/CD流程调整
这就像多米诺骨牌。你以为只是推倒第一张牌,结果整个牌阵都塌了。
我坐在工位上盯着那个Jira工单,内心只有一个疑问:就为了一个新的Hook名字,值得吗?
这一刻,我突然意识到:我们可能在一个巨大的框架陷阱里越陷越深。
你经历过几轮框架更替?
如果你是2010年后入行的前端开发者,那么你很可能经历过这样的时间线:
go
时间轴:前端框架的变迁史
2010-2012: jQuery统治时代
└─ "用jQuery改个DOM真方便!"
2013-2015: Angular.js 崛起
└─ "双向绑定太酷了!"
└─ Angular 2发布,API完全重写
└─ "我的项目代码全废了..."
2015-2018: React 大爆发
└─ "虚拟DOM + 组件化是未来!"
└─ Redux、MobX、Flux各种状态管理百家争鸣
2018-2020: Vue 异军突起
└─ "更简单的API!"
└─ Vue 3发布,Composition API
└─ "又要重新学习..."
2020-2025: 框架大战白热化
├─ Svelte (编译时优化)
├─ Solid (更细粒度的响应式)
├─ Qwik (可恢复性架构)
└─ 各种元框架
├─ Next.js
├─ Nuxt.js
├─ Remix
├─ SvelteKit
└─ Astro
2026-未来: ???
└─ 你猜明年又会出什么新框架?
平均下来,每1.5-2年就会有一个新的"前端革命"。
这就像你刚学会骑自行车,有人就告诉你:"自行车已经过时了,现在流行电动滑板车。"等你刚学会滑板车,又有人说:"滑板车太慢了,现在都用飞行器了。"
问题是,你要去的地方可能就在500米外。
框架不是在消亡,而是"框架信仰"在消亡
先说清楚,我不是在宣布React或Vue的死刑。
React不会消失。Vue不会崩盘。Svelte也不会和jQuery手牵手走向夕阳。
但"框架是万能解药"这种思维模式,在即将到来的2026年,正在加速瓦解。
我们正在进入一个新阶段:
-
浏览器原生API终于变得强大且好用
-
前端工具链变得更模块化
-
性能优化重新成为关注焦点
-
框架从"必选项"变成了"可选项"
越来越多开发者开始意识到一个简单的事实:
你不需要2MB的运行时和虚拟DOM,只为了更新一个按钮的文本内容。
听起来很荒谬,但这就是我们过去十年一直在做的事。
为什么框架会流行?因为JavaScript曾经太烂
我们需要诚实地面对一个历史事实:
框架之所以流行,不是因为它们有多优雅,而是因为原生JavaScript当年确实太难用。
十年前的痛点
在2010-2015年那个时代:
DOM操作是噩梦
go
// 2013年的代码,看着都头疼
var elements = document.getElementsByClassName('items');
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', function(e) {
// 这里的this指向谁?
// i的值是多少?
// 闭包陷阱等着你
});
}
浏览器兼容是灾难
go
// 要兼容IE8-IE11,你需要这样写
var xhr = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP");
// 或者判断事件绑定方式
if (element.addEventListener) {
element.addEventListener('click', handler);
} else {
element.attachEvent('onclick', handler);
}
状态管理全靠胶带
go
// 状态散落各处
var userData = {...};
var isLoggedIn = false;
var cartItems = [];
// 更新状态后手动同步DOM
function updateUI() {
if (isLoggedIn) {
document.getElementById('username').textContent = userData.name;
document.getElementById('cart-count').textContent = cartItems.length;
// 忘记更新某个地方?恭喜你得到一个bug
}
}
框架解决了这些痛点,给了我们:
-
抽象层(不用关心底层DOM)
-
统一模式(组件化思维)
-
工程化工具(打包、热更新、类型检查)
-
开发效率(告别手动操作DOM的地狱)
但这是2013年的故事。现在是2025年底,即将跨入2026,世界早已天翻地覆。
现代浏览器的逆袭:原生API不再是笑话
示例1:现代JavaScript的DOM操作
2013年(需要jQuery):
go
// 需要引入30KB的jQuery
$('.save-btn').on('click', function() {
$.ajax({
url: '/api/save',
method: 'POST',
data: { content: $('.editor').val() },
success: function(res) {
$('.save-btn').text('已保存!');
},
error: function() {
$('.save-btn').text('保存失败');
}
});
});
2025年(原生JavaScript):
go
// 不需要任何库,代码简洁清晰
document.querySelector('.save-btn').addEventListener('click', async () => {
const btn = event.currentTarget;
const content = document.querySelector('.editor').value;
try {
const response = await fetch('/api/save', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content })
});
btn.textContent = response.ok ? '已保存!' : '保存失败';
} catch (error) {
btn.textContent = '网络错误';
}
});
这段代码:
-
可读性强
-
不需要jQuery的30KB体积
-
不需要React的状态管理
-
不需要任何运行时库
示例2:Web Components不再是空中楼阁
很多人对Web Components的印象停留在"听起来不错,但实际没法用"。
但现在情况不同了。看看这个计数器组件:
go
// 一个完整的、可复用的、原生的计数器组件
class CounterButton extends HTMLElement {
constructor() {
super();
this.count = 0;
}
connectedCallback() {
this.render();
this.addEventListener('click', () => {
this.count++;
this.render();
});
}
render() {
this.innerHTML = `
<button class="counter-btn">
点击次数: ${this.count}
</button>
`;
}
}
// 注册组件
customElements.define('counter-button', CounterButton);
// 使用(就像原生HTML标签一样)
// <counter-button></counter-button>
这个组件:
-
可复用:可以在任何HTML页面中使用
-
原生支持:无需任何框架
-
零依赖:不会增加bundle体积
-
封装性强:样式和逻辑都在组件内部
对比React:
go
// React版本需要整个React运行时(~130KB)
import { useState } from 'react';
function CounterButton() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
点击次数: {count}
</button>
);
}
功能完全一样,但React版本需要额外的130KB运行时。如果你的整个页面就只需要这一个简单交互,使用React就是在用火箭筒打蚊子。
我们掉进了"框架信仰"的陷阱
这才是真正的问题所在。
我们使用框架,很多时候不是因为需要,而是因为:
1. 惯性思维
"我一直用React,所以这个项目也用React"
2. 简历驱动开发
招聘要求写着:"要求精通React" 不是"要求精通Web开发"
3. 面试门槛工具
面试官问:"说说React的虚拟DOM原理" 不问:"你如何优化页面性能"
4. 技术身份认同
"我是React开发者"成了身份标签 "我是Web开发者"反而显得不够专业
这就好比:
你买了一台顶配的游戏电脑(框架),但你每天只用它来写Word文档(简单交互)。
有人问你:"为什么不买个便宜点的办公电脑?"
你回答:"因为我是游戏玩家(React开发者),我们都用游戏电脑(React)。"
但实际上,你上一次玩游戏是三个月前。
框架仍然有其不可替代的价值
说了这么多,我不是要否定框架的价值。
在某些场景下,框架依然是最佳选择:
场景1:大型设计系统
假设你在字节跳动工作,需要维护一套在抖音、今日头条、西瓜视频等多个产品中复用的设计系统。
这种情况下:
-
需要数百个可复用组件
-
需要统一的状态管理
-
需要严格的类型检查
-
需要完善的测试覆盖
React + TypeScript + 自研组件库是合理的选择。
场景2:复杂的数据可视化面板
如果你在做类似阿里云控制台、腾讯云监控面板这种复杂的数据可视化应用:
go
用户界面复杂度分析:
├─ 实时数据流(WebSocket推送)
├─ 复杂的状态管理(全局状态 + 组件状态)
├─ 大量交互组件
│ ├─ 图表联动
│ ├─ 筛选条件同步
│ └─ 数据刷新机制
└─ 性能优化需求
├─ 虚拟列表
├─ 按需加载
└─ 记忆化计算
这种场景下,React/Vue的虚拟DOM、状态管理、组件化都能发挥巨大价值。
场景3:大型团队协作
如果你的团队有50+前端开发者,使用统一的框架可以:
-
降低代码审查难度
-
简化新人onboarding
-
统一最佳实践
-
复用组件和工具
这时候框架带来的"规范性"价值远大于性能成本。
但大多数项目真的需要吗?
问题在于,大多数项目其实没有这么复杂。
你的To-Do应用不需要:
-
❌ 客户端路由(SPA有什么必要?)
-
❌ 虚拟DOM diff算法(列表就10条数据)
-
❌ 10层状态管理抽象(就一个checkbox状态)
-
❌ CSS-in-JS运行时(静态CSS不香吗?)
你的落地页不需要:
-
❌ Redux状态管理(页面就3个区块)
-
❌ React Router(就一个页面)
-
❌ 服务端渲染(SEO用meta标签就够了)
-
❌ 130KB的运行时(首屏速度更重要)
你的个人博客不需要:
-
❌ 复杂的构建流程
-
❌ 组件化抽象(模板就够了)
-
❌ 状态管理(数据都在Markdown文件里)
我们花了几个小时配置Webpack/Vite,引入React,搭建状态管理,最后做出来的东西,用20行原生JavaScript就能实现。
这不是在剃牦牛毛,这是在剃大象的毛。
新趋势:更小、更轻、更务实
好消息是,业界正在纠偏。
新一代工具正在出现:
1. 微型库的崛起
htmx(14KB)
go
<!-- 用HTML属性实现AJAX请求,不需要写JavaScript -->
<button hx-post="/api/like" hx-target="#likes">
点赞
</button>
<div id="likes">0</div>
Alpine.js(15KB)
go
<!-- 轻量级的响应式,直接写在HTML里 -->
<div x-data="{ count: 0 }">
<button @click="count++">点击</button>
<span x-text="count"></span>
</div>
2. 元框架的智能化
Astro(零JavaScript默认)
go
---
// 服务端渲染,客户端零JavaScript
const posts = await getPosts();
---
<div>
{posts.map(post => (
<article>{post.title}</article>
))}
</div>
Qwik(可恢复性架构)
-
不需要hydration
-
按需加载JavaScript
-
极致的性能优化
3. 回归渐进增强
go
传统SPA架构:
JavaScript失败 → 整个页面挂掉 → 白屏
渐进增强架构:
JavaScript失败 → 基础功能仍可用 → 体验降级但可用
这就是Web的本质:内容优先,交互增强。
实战建议:如何选择合适的技术栈
决策流程图
go
开始新项目
↓
问自己:这个项目有多复杂?
↓
├─ 简单(落地页、博客、简单交互)
│ ↓
│ 尝试原生JavaScript + CSS
│ 或使用轻量级库(Alpine.js、htmx)
│ ↓
│ 体积 < 50KB,首屏 < 1s
│
├─ 中等(企业官网、小型管理后台)
│ ↓
│ 使用元框架(Astro、Eleventy)
│ + 少量React/Vue组件
│ ↓
│ 按需加载,SSR优先
│
└─ 复杂(大型SaaS、数据可视化、设计系统)
↓
使用成熟框架(React、Vue)
+ 完整的工程化方案
↓
优化性能,代码分割
五条实战原则
原则1:先问"为什么",再选工具
不要一上来就问"用React还是Vue"。
先问:
-
这个项目的核心价值是什么?
-
用户最关心的是什么?(速度?功能?体验?)
-
我真的需要这么复杂的工具吗?
原则2:从简单开始,按需升级
go
第一步:用原生HTML+CSS实现静态版本
第二步:用原生JavaScript添加基础交互
第三步:如果复杂度上升,引入轻量级库
第四步:如果还不够,再考虑React/Vue
不要反着来。不要一开始就搭建React脚手架,然后发现"好像用不到这么多功能"。
原则3:不要用框架定义你的职业身份
你的职位不叫"React开发工程师",你的职位叫"前端开发工程师"。
你的技能不是"精通JSX",你的技能是"精通构建用户界面"。
React只是工具,不是目的。
原则4:优先采用工具,而非生态系统
go
好的选择:
├─ 用Vite做构建(快速、轻量)
├─ 用Astro做SSR(按需加载)
└─ 用Alpine.js做交互(15KB)
不好的选择:
├─ 引入完整的Next.js(因为"大家都用")
├─ 配置复杂的Webpack(因为"更灵活")
└─ 引入整个Vue生态(因为"生态完善")
工具要解决具体问题。生态系统会绑架你的架构。
原则5:接受简单不等于退步
很多开发者觉得"用原生JavaScript"显得不够专业。
但实际上:
复杂≠专业 简洁≠业余 原生≠过时
能用最简单的方案解决问题,才是真正的专业。
所以,框架的时代结束了吗?
答案是:没有,但框架垄断的时代,在2026年即将正式终结?。
站在2025年的尾巴上,回望过去十年的前端发展,我们告别的不是框架本身,而是:
-
❌ 盲目跟风
-
❌ 单一技术栈统治
-
❌ 依赖地狱
-
❌ 过度工程化
我们迎来的是:
-
✅ 理性选择
-
✅ 务实主义
-
✅ 平台优先思维
-
✅ 性能意识回归
框架不会消失,但 "框架是唯一答案"这个谎言正在破产。
如果我们更少地选择框架,我们就会更好地使用框架。
下一次,当你看到一个patch版本升级需要三天工期时,也许你会停下来思考:
"我真的需要这个框架吗?"
也许答案是"需要",也许是"不需要"。
但至少,你思考过了。
这就是进步。
写在最后
2025年即将结束,2026年即将到来。
在这个特殊的时间节点,如果这篇文章让你有所思考,无论是认同还是反对,都欢迎在评论区留言讨论。
技术没有绝对的对错,只有适合与不适合。
如果你正在经历框架升级的痛苦,或者正在为2026年的技术选型做规划,这篇文章希望能给你一些启发。
新年新气象,也许2026年可以尝试一些不一样的技术选择?
觉得有帮助?点个赞,让更多开发者看到👍
关注《前端达人》,我们一起探讨前端技术的本质,不追风口,只追真理
点击分享,把这篇文章推荐给正在React 18升级到19的朋友,给他们一点精神支持😄