⚛️ 2013–2018 SPA 时代
一句话定性
一句话改变了一切:
UI = f(state)。前端不再手动操作 DOM,而是声明”UI 应该长什么样”,剩下的交给框架。组件化 + 声明式 + 虚拟 DOM,把前端从”页面制作”升级成”软件工程”。
一、背景:行业现状
Ajax 时代证明了”网页可以是应用”,但用 jQuery 写出来的复杂应用是一场维护噩梦。整个行业都在寻找一种能管理复杂状态的新范式。
- 2010 年 AngularJS 横空出世,Google 出品,“双向数据绑定 + 依赖注入 + 指令系统”,一度被奉为”前端的未来”。
- 2013 年 5 月,Facebook 开源 React,带来三个颠覆性概念:虚拟 DOM、单向数据流、组件即函数。初期因 JSX(“HTML 写在 JS 里?亵渎!”)遭群嘲,但很快真香。
- 2014 年,尤雨溪(Evan You)发布 Vue,取 Angular 的数据绑定 + React 的组件化,主打”渐进式、易上手”。
- 2016 年,Google 推倒重来发布 Angular-2+(与 AngularJS 完全不兼容),拥抱 TypeScript 和组件化。
- ES6-ES2015(2015)发布,带来
class、箭头函数、let/const、Promise、模板字符串、原生模块(ES-Modules)——语言本身现代化,为框架提供了趁手的工具。
这是前端框架的”战国时代”,最终格局基本是:React 领先、Vue 紧随、Angular 守住企业级阵地。
二、核心痛点:开发者面临什么
jQuery 解决不了的事
- 状态与视图同步是 bug 之源:命令式操作下,改数据要手动改 DOM,改 DOM 要手动改数据,稍有遗漏就不一致。
- 没有真正的组件复用:jQuery 插件无法封装”状态+视图+行为”;复制粘贴是常态。
- 大型应用没有架构约束:谁都能在任何地方改任何 DOM,代码无法推理(reasoning)。
- 频繁操作真实 DOM 性能差:DOM 操作是浏览器里最慢的事之一,手动优化又极易出错。
- 路由、状态、数据流全靠拼:做一个”单页应用”要自己拼路由、拼状态管理、拼数据请求。
核心矛盾:应用复杂度已经超过了”人脑能手动同步状态和视图”的上限,需要一种机制让这件事自动化、可推理。
三、代表技术
| 技术 | 角色 | 专题 |
|---|---|---|
| AngularJS (2010) | 先驱:双向绑定的开创者,也是反面教材 | AngularJS |
| React (2013) | 时代定义者:虚拟 DOM + 单向数据流 | React |
| Vue (2014) | 平衡之道:易用性之王,中国崛起 | Vue |
| Angular-2+ (2016) | 企业级全家桶 + TypeScript 原生 | Angular-2+ |
| JSX | ”把 UI 当作 JS 表达式”的关键创新 | React |
| 虚拟 DOM (Virtual DOM) | 让声明式渲染在性能上可行的核心机制 | React |
| Redux (2015) | 单向数据流的状态管理范式 | Redux |
| ES6-ES2015 | 语言现代化,框架的基础设施 | ES6-ES2015 |
| Webpack (2014→) | 模块打包器,把组件化工程落地 | Webpack |
| Babel | 让 JSX/ES6 能在老浏览器跑 | Babel |
四、为什么诞生:技术出现的原因
- React 为什么用虚拟 DOM? Facebook 的痛点是:聊天/通知的未读数等状态,在大型应用里手动同步 DOM 几乎不可能不出 bug。React 的解法极其大胆:别管怎么改 DOM,你只要每次都”重新描述”整个 UI 长什么样(
UI = f(state)),我用一个内存中的虚拟 DOM 做 diff,只把变化的部分应用到真实 DOM。这把”如何更新”的责任从开发者手里彻底拿走了。 - JSX 为什么反而是优点? 当时主流认为”模板和逻辑要分离”。React 反其道而行:UI 本质上就是逻辑的一部分,把它们放在一起(JSX)反而更内聚。这个”离经叛道”的选择,后来被证明是对的。
- Vue 为什么出现? 尤雨溪在 Google 用 AngularJS,觉得它”太重、太多概念”。他想要”只取最好的部分”:Angular 的数据绑定 + React 的组件化,但更轻、更渐进、更易学。一个人就能从
<script>标签引入开始用,不需要一上来就上全套工具链。详见 为什么Vue在中国崛起。 - Angular 为什么推倒重来? AngularJS 的双向绑定 + 脏检查(dirty checking)在大型应用里性能崩溃,架构也无法适配组件化潮流。Google 索性 2.0 完全重写,赌上 TypeScript 和 RxJS,做成企业级”全家桶”。代价是抛弃了整个 AngularJS 生态(社区至今心有余悸)。
- Redux 为什么出现? 组件多了,跨组件共享状态成了难题(数据要层层透传)。受 Flux 架构和 Elm 启发,Redux 提出”单一数据源 + 纯函数 reducer + 不可变更新”,让状态变化可预测、可追溯(时间旅行调试)。详见 Redux。
五、解决了什么:具体价值
- 声明式彻底消灭了”手动同步状态和视图”这个最大 bug 源。开发者只需关心”数据是什么样”,UI 自动跟随。
- 组件化让 UI 第一次可以真正复用和组合:一个
<Button>可以封装状态、样式、行为,到处复用。前端开始有了”软件工程”的样子。(把样式也封进组件的需求,直接催生了 CSS-in-JS 和 组件库。) - 虚拟 DOM 让”每次重渲染整个 UI”在性能上变得可行(虽然后来证明它并非总是最优,见副作用)。
- 单向数据流(React/Redux)让大型应用的状态可推理:数据流向单一,出了 bug 能顺着流向追踪。
- 前端正式从”切图仔/页面仔”独立为一个完整的工程岗位,有了自己的架构、工具链、最佳实践。
六、带来的新问题:技术债与缺陷
SPA 的胜利,埋下了下一个时代的全部痛点
- 首屏白屏 + SEO 灾难:SPA 把渲染全搬到客户端,首次加载要先下载一大坨 JS、再执行、再渲染。用户先看到白屏;搜索引擎爬虫看到的是空
<div id="root">。这个痛点直接催生了 SSG 的回归。- JS 体积爆炸:框架 + 组件 + 依赖,bundle 越来越大,移动端和弱网下体验崩坏。
- 工具链复杂度失控:要用 React/Vue,你得先会 Webpack、Babel、loader、plugin、polyfill……”配置一个项目”本身成了专业技能。这是下一个”工程化时代”的核心矛盾来源。
- 状态管理过度工程化:Redux 的样板代码(action / reducer / dispatch)被诟病”为了改一个值要写三个文件”,催生了后来的 MobX、Zustand 等”反样板”方案。
- 虚拟 DOM 不是银弹:它有运行时开销,diff 也要成本。这个反思后来直接催生了 Svelte(“编译时干掉虚拟 DOM”)和 编译时优化的整条路线。
- AngularJS 留下生态创伤:2.0 的不兼容重写,让大量项目无路可走,也成了”框架不能轻易破坏向后兼容”的著名教训。
七、对下一代技术的影响:因果链
SPA 把渲染全搬到客户端
│
├──► 首屏白屏 + SEO 差 ──► SSR/SSG 回归 ──► Next.js / Nuxt 兴起
│ ──► 进入渲染模式的螺旋(SSR→SSG→ISR→RSC)
│
├──► 工具链复杂到失控 ──► "工程化"成为独立战场 ──► 进入 [[2018-2023 工程化时代]]
│ (Webpack 太慢 → Vite;Babel/Terser → esbuild/SWC)
│
├──► 虚拟 DOM 有开销 ──► Svelte(编译时)、Solid(细粒度响应)反思路线
│
└──► Redux 样板太多 ──► MobX / Zustand / Recoil 等轻量状态方案
│
↓
React 自己也在进化:Hooks(2019) → Concurrent → Server Components(RSC)
📊 本时代技术因果图
这张图聚焦本时代内部:谁因为谁的什么痛点而出现
flowchart TD imperative["jQuery 命令式痛点<br/>手动同步状态/视图"] declare["对声明式的渴望<br/>只描述 UI 长什么样"] angularjs["AngularJS 2010<br/>双向绑定 + 脏检查"] react["React 2013"] vue["Vue 2014"] angular2["Angular 2+ 2016"] vdom["虚拟 DOM"] oneway["单向数据流"] comp["组件化"] crossstate["跨组件共享状态难<br/>(数据层层透传)"] redux["Redux 2015<br/>单一数据源 + reducer"] es6["ES6 2015<br/>class / 箭头 / 模块"] spa["SPA 单页应用"] imperative -->|"不可维护, 无组件复用"| declare declare -->|"UI = f(state) + 虚拟 DOM"| react declare -->|"渐进式, 只取最好的部分"| vue angularjs -->|"双向绑定+脏检查在大应用性能崩溃"| react angularjs -->|"概念太重, 想要轻量"| vue angularjs -->|"推倒重来, 拥抱 TS"| angular2 react --> vdom react --> oneway react --> comp comp -->|"组件一多"| crossstate crossstate -->|"受 Flux/Elm 启发"| redux es6 -->|"语言现代化, 给框架趁手工具"| react vdom -->|"声明式渲染在性能上可行"| spa react --> spa spa -.->|"伏笔: 渲染全搬到客户端, 首屏白屏 + SEO 灾难"| ssr["SSR / 工程化时代"] redux -.->|"伏笔: 样板代码太多, 催生 Zustand 等"| light["轻量状态方案"] classDef next fill:#eceff1,stroke:#607d8b,stroke-dasharray:4 3; class ssr,light next;
本时代的历史地位
SPA 时代是前端的”工业革命”:声明式 + 组件化 + 虚拟 DOM 三大发明,把前端从手工作坊变成了流水线工厂。
UI = f(state)是整个现代前端的”牛顿第一定律”,至今所有主流框架都建立在它之上。但工业化也带来了工业污染——白屏、SEO、巨型 bundle、失控的工具链——这些副作用,正是下一个时代要清理的烂摊子。
🔗 上一篇:2005-2013 Ajax时代 | 下一篇:2018-2023 工程化时代 🔗 相关专题:React | Vue | AngularJS | Angular-2+ | Redux | 为什么React战胜了AngularJS