01|库不再够用的那一刻,前端第一次需要的是“宪法”
上一篇讲到,
jQuery 这类库先统一了浏览器现实。
它们把 DOM、事件、Ajax 这些脏活做顺了,
让前端终于开始像一门能日常干活的工作。
可也正因为它们把活做顺了,
更高层的问题反而会更快冒出来。
因为当 Web 已经越来越像应用时,
前端真正开始难受的,不再只是:
- 选元素烦不烦
- 绑事件麻不麻烦
- 发请求顺不顺手
而会变成:
- 状态到底放哪里
- 界面和数据怎么对应
- 路由怎么管理
- 多个视图怎么协同
- 大项目怎么不烂成一锅
也就是说,前端这时候第一次真正大规模需要的,
已经不是更强的工具箱。
而是:
更像“宪法”的结构。
所以 2010 年前后那批框架集中冒出来,
并不是什么巧合。
它们其实都是在回应同一个历史压力:
浏览器已经不像一个脚本补丁场了,它开始像一个需要长期治理的应用现场。
02|Backbone 代表的是一种特别克制的立法:给你结构,但不替你统治太多
这批框架里,Backbone 很有代表性。
因为它很早就把自己的问题意识说得很清楚:
Backbone.js gives structure to web applications
这句话非常值得记。
因为它抓到的已经不是“某个 API 好不好用”。
而是:
应用需要结构。
Backbone 的做法很像一种最小立法。
它给你:
ModelCollectionViewRouter- 事件系统
可它并不想替你把一切都规定死。
你可以把它理解成一种很典型的早期框架气质:
我承认浏览器应用需要更稳的结构,但我不想替你决定太多。
这条路线为什么会有吸引力?
因为在那个阶段,很多开发者已经意识到页面脚本越来越撑不住。
可他们也还没有准备好接受一个太重、太全、太爱替你立规矩的系统。
于是 Backbone 提供了一种特别讨巧的过渡形态:
既承认“应用需要结构”,又尽量保留开发者对结构的主导权。
这也是为什么很多人后来回头看 Backbone,
会觉得它不像后来那种“全家桶型框架”。
它更像:
前端第一次承认自己需要架构,但还舍不得交出太多自由。
03|Knockout 则把另一件事推到了前台:界面和状态的关系,最好别再手工硬缝
和 Backbone 相比,
Knockout 更像是从另一侧切进来的。
它最强的问题意识,不是“整体结构最小够不够”。
而是:
界面和数据之间的关系,能不能别再靠手工同步。
它在首页和文档里特别强调:
MVVM pattern- declarative bindings
- dependency tracking
- automatic UI refresh
这背后真正打中的,是当时浏览器应用最痛的一层现实:
状态变化越来越频繁,而手工维护 DOM 与状态一致性,已经开始越来越不体面了。
这就是 Knockout 很值得写的一点。
因为它让前端世界第一次更明确地感受到:
“绑定”本身也可以成为核心能力。
以前大家更习惯的思路是:
- 先拿到数据
- 再自己改 DOM
- 再自己补事件
- 再自己维持状态
而 Knockout 在推动的,是另一种感觉:
让数据模型自己更直接地拖动界面。
你当然可以说,这条线后来也带来了很多问题。
可在当时,它确实精准命中了一个正在爆炸的痛点:
前端越来越不想亲手缝每一次 UI 更新了。
04|Ember 的野心更大:它不只是想给结构,它是想直接给你一整套秩序
如果说 Backbone 像最小立法,
Knockout 像在强化状态和视图的绑定关系,
那 Ember 代表的就是另一种更强势的路线:
既然浏览器应用已经够复杂,那就别再只给零件了,直接给一整套秩序。
这也是为什么 Ember 这条线特别值得单独看。
因为它是前端框架史里非常典型的一种雄心:
- 约定优于配置
- 完整框架
- 组件、路由、数据流、CLI、发布节奏一起组织
到 Ember 1.0 Released 那篇公告时,
它甚至已经在公开强调:
the pain ... is now over
这句话特别有戏。
因为它不是在说:
“我们又新增了几个 API。”
它是在说:
前端过去那种混乱而反复变化的架构痛,终于应该结束了。
而且 Ember 后来很快推动出更明确的发布节奏、稳定版本、实验特性入口,
也说明它争的根本不是一个“小而美库”的位置。
它想争的是:
浏览器应用该如何被完整治理。
Ember 这条线后来虽然没有拿到最大市场,
可它的历史作用非常大。
因为它提前把一种后来大家越来越熟悉的框架形态做出来了:
框架不是几个核心 API,而是一整套默认组织方式。
05|AngularJS 为什么当年会这么有吸引力:因为它看起来真的像在替你接管复杂度
很多后来才入行的人,容易低估 AngularJS 当年的冲击力。
因为今天回头看,你很容易先注意到它的历史包袱、脏检查、迁移断裂这些后果。
可如果要写历史,就必须先回到它最有吸引力的时候。
AngularJS 当年强的地方,正在于它给人的感觉是:
你不用再自己一点点拼应用了,框架会替你接手很多以前你得手工扛的复杂度。
它吸引人的点,很集中:
- 模板驱动
- 双向绑定
- 依赖注入
- 指令系统
- 完整应用结构
如果你把它放回那个时间点看,
它的诱惑其实非常大。
因为在很多团队眼里,
这几乎像是在说:
前端终于有一套像样的大应用方法论了。
而这也正是 AngularJS 值得写的地方。
它不只是一个流行框架。
它是一种特别强势的历史回答:
既然浏览器应用已经这么复杂,那就别再犹豫了,直接把更多秩序交给框架。
当然,后来的历史也说明,
把太多复杂度压给框架内部机制,会带来新的问题。
可在它崛起的那个瞬间,
这恰恰是它最迷人的地方。
因为它看起来像真的能一次性替团队把混乱收编掉。
06|把这几条线放在一起看,你会发现它们都在争同一件事:谁来解释前端应用的合法形态
Backbone、Knockout、Ember、AngularJS 表面差很多。
可如果退一步看,会发现它们其实都在抢同一个位置。
它们都在回答:
前端应用到底该长成什么样,才算“合理”。
只是它们各自交出的答案不一样。
Backbone 说:
先给最小结构,别替开发者决定太多。
Knockout 说:
重点是把数据和界面的对应关系做顺。
Ember 说:
别零敲碎打了,直接上完整秩序。
AngularJS 说:
既然复杂度已经失控,那就把更多控制权交给框架。
也就是说,这个阶段最关键的变化不在于:
“框架变多了。”
而在于:
前端第一次开始大规模争论,浏览器应用的合法形态到底应该是什么。
这就是为什么我更愿意把这一阶段叫“抢架构解释权”。
因为这批框架真正竞争的,
已经不是局部能力。
而是:
谁有资格定义应用结构的默认答案。
07|可它们最后都没有彻底坐稳天下,因为它们仍然在回答旧问题
这批框架的历史意义很大,
但它们也并没有彻底终结战争。
原因不难理解。
因为它们虽然都在认真回答“浏览器应用怎么组织”,
可它们大多还是站在一种旧一点的 UI 直觉上:
- 模板很重要
- 视图层和数据层要靠绑定或控制器协调
- 应用结构更像传统 MVC / MVVM 的前端变体
这条线当然在当时有很强合理性。
但随着前端继续变重,
另一个更激进的问题会慢慢浮出来:
如果 UI 本身可以直接被理解成状态的投影,那我们是不是根本不需要再沿着模板、控制器、双向绑定那套心智继续走下去?
这就是下一轮大改道的入口。
也就是 React 这条线真正要切进来的位置。
它不是简单再做一个框架。
它会从更底层改写问题:
别再问“模板和控制器怎么配合”,改问“状态如何渲染成界面”。
08|很多今天的框架常识,其实都是那一轮立下的规矩
为什么这一段前史今天还值得认真写?
因为很多现代前端里最习以为常的东西,
其实就是在这场 MVC / MVVM 爆发期先被推成常识的。
比如:
- 前端应用应该有路由
- 前端应用应该有组件或视图层边界
- 前端应用应该有状态与界面的系统性关系
- 前端项目应该有统一的组织方式
这些今天看起来像常识,
可在当时其实都是打出来的。
而且直到今天,
我们依然还在反复回答同样的问题:
- 框架到底该管多宽
- 该给开发者多少自由
- 该靠模板、运行时还是编译器
- 状态和视图之间到底该怎样耦合
所以这段历史真正值得记住的,不是:
“曾经有很多老框架。”
而是:
当前端第一次发现自己需要的不只是库,而是一整套浏览器应用宪法时,所有人都在抢着解释:一个前端应用到底该怎样才算合法。
下一篇要讲的,就是这场争夺里的最大改道者:
为什么 React 最后赢下的,不只是一个框架位置,而是整套 UI 的思考方式。
参考与延伸阅读
Backbone.js
https://backbonejs.org/Backbone Annotated Source
https://backbonejs.org/docs/backbone.htmlKnockout : Introduction
https://knockoutjs.com/documentation/introduction.htmlKnockout : Home
https://knockoutjs.com/Ember 1.0 Released
https://blog.emberjs.com/ember-1-0-released/The Post-1.0 Release Cycle
https://emberjs.com/blog/2013/09/06/new-ember-release-process.htmlEmber Guides: Core Concepts
https://guides.emberjs.com/release/getting-started/core-concepts/Defining Your Routes - Ember Guides
https://guides.emberjs.com/release/routing/defining-your-routesAngularJS Guide: Directives
https://docs.angularjs.org/guide/directiveAngularJS Guide: Dependency Injection
https://docs.angularjs.org/guide/diAngularJS Guide: Controllers
https://docs.angularjs.org/guide/controllerThank you, Angular
https://blog.angular.dev/thank-you-angular-d90d70f2e9d8Finding a Path Forward with AngularJS
https://blog.angular.dev/finding-a-path-forward-with-angularjs-7e186fdd4429