01|前端工程化最早不是“大家突然爱上了复杂工具”,而是前端这件事本身先变了
今天很多人一说起前端工程化,第一反应往往是:
- 配置太多
- 工具太重
- 构建太慢
- 学习成本太高
于是很容易顺着得出一个结论:
前端从一开始就是一门特别依赖工程体系的开发工作。
可如果你把时间线往前拉,就会发现这结论并不成立。
因为最早的前端,根本不是在“工程化默认开启”的世界里长大的。
它最初的工作内容更像是:
- 做页面结构
- 调样式
- 补一点脚本交互
- 把静态文件放上服务器
那个时代的“发布”,很多时候真的接近于:
把文件放对位置。
没有 bundler。
没有 dev server。
没有 HMR。
更没有今天这种“写完代码先过十几道工具链”的默认现实。
所以第一篇最重要的起点不是“工具后来为什么这么多”。
而是要先问清楚:
为什么一个本来几乎不需要构建系统的领域,后来会一步步被逼到离不开构建系统。
02|因为最早的前端,首先是页面时代,不是应用时代
这层非常关键。
很多后来者容易把今天的前端直觉,误投回早期 Web。
可早期网页面对的现实,和今天完全不是一回事。
那时网页的基本模型仍然更接近“文档 + 一点增强”:
- 页面跳转是主流程
- 服务器返回整页 HTML 是常态
- JavaScript 更多是补充行为,而不是承载整套应用逻辑
在这种结构下,前端代码当然也会增长。
但增长速度、组织压力、交付压力,都还没有大到一定要把“构建”独立成一门学问。
因为在那个阶段,很多问题还能靠朴素办法撑住:
<script>标签手工引入- CSS 文件手工拆分
- 图片手工整理
- 改完直接上传
也就是说,最早的前端当然不是没有复杂度。
只是那种复杂度还没有系统性外溢成:
一套必须被专门治理的交付复杂度。
所以这篇一开始必须先立住一句:
前端最早不是没有工程问题,而是它最初面对的页面规模和交付节奏,还不足以逼出完整工程体系。
03|可即便在那个时代,最早的裂缝也已经出现了:代码一多,script 标签和手工顺序就开始变得脆弱
最早的前端代码组织方式,其实和模块化前史很像:
把脚本通过 <script> 标签一个个挂进页面。
谁先加载,谁先执行。
后面的脚本想用前面的东西,就默认去全局里拿。
这套办法在脚本很小时并不离谱。
因为那时页面上的脚本常常只是:
- 表单校验
- 菜单交互
- 一点动画
- 一点 DOM 操作
可一旦页面功能开始变多,问题就会迅速冒出来。
因为这套办法要求开发者同时手工维持很多事:
- 哪个文件先引
- 哪个文件后引
- 哪些变量不能撞名
- 哪些库依赖哪些库
它表面上看是“文件管理”。
本质上已经是在手工维护一套非常原始的依赖系统。
而且这套依赖系统有两个特别糟糕的特征:
第一,它不显式。
第二,它特别容易因为顺序和规模扩大而坏掉。
也就是说,前端最早的问题虽然还不叫“工程化”,
但裂缝已经很明显了:
代码一旦开始变长,页面开发就不再只是写几个脚本,而是在手工维持一套脆弱的资源装配过程。
04|但真正把事情推到下一个阶段的,还不是代码组织,而是性能压力开始直接反过来规定你该怎么交付文件
这一步,才是前端工程化前史里真正重要的拐点。
因为如果问题只是“文件顺序有点烦”,很多团队其实还能继续忍。
真正让“构建需求”开始变硬的,是性能。
随着网页越来越丰富,前端资源也越来越多:
- 脚本更多
- 样式更多
- 图片更多
- 请求更多
而浏览器加载页面,本来就不是只拿 HTML。
它还要拿脚本、样式、图片,以及后面越来越多的静态资源。
这时候,前端团队会很快撞上一条后来几乎写进常识里的性能逻辑:
请求太多,会慢。
Yahoo! Exceptional Performance 团队后来把这件事概括得非常直接:
Make Fewer HTTP Requests
Steve Souders 也把“减少 HTTP 请求”放在高性能网页实践里最靠前的位置,并明确把合并脚本、合并样式视为重要手段。
这意味着什么?
意味着从这个时候开始,前端已经不只是要把代码写对。
还要把资源交付成:
- 更少的请求
- 更小的体积
- 更快的首屏加载
这一步非常重要。
因为它让前端第一次被迫面对一个后来会反复出现的大矛盾:
开发时你希望文件拆得清楚一点,交付时你却希望文件尽量少一点。
这就是工程化真正开始长出来的土壤。
05|于是最早长出来的,不是现代意义上的工具链,而是一批很朴素但已经很工程化的交付动作
很多人会把“工程化”理解得过于狭窄。
仿佛只有出现了 webpack、Vite、Babel 这类名字,前端才算工程化。
其实不是。
更早的时候,虽然还没有今天这样的统一工具层,
但很多典型的工程动作已经出现了。
比如:
- 开发时拆很多文件,发布时手工合并
- 上线前把脚本压缩
- 给静态资源开压缩和缓存策略
- 把源码目录和发布目录分开
- 人肉维护一个“开发版 / 线上版”的差异
这些动作看起来朴素,甚至土。
可它们已经在回答一个非常工程化的问题:
同一份前端代码,怎样从“便于开发”转成“便于交付”。
换句话说,前端工程化并不是突然从天而降的。
它最早是以一种很原始的形态出现的:
先把开发态和发布态区分开。
而只要这件事一发生,工程化其实就已经开始了。
06|网页应用化让这场矛盾彻底升级:从“页面里有点脚本”变成“页面本身越来越像应用”
如果说性能压力让前端第一次开始认真想“怎么交付”,
那 Ajax 和网页应用化,则让这件事彻底从边缘问题变成中心问题。
Jesse James Garrett 在 2005 年那篇著名文章里,把 Ajax 描述成一种“对 Web 应用的新方法”。
这句话的历史意义非常大。
因为它点明了一件后来几乎决定前端命运的事实:
网页不再只是被动展示的页面,而开始承受越来越多应用级交互。
一旦网页越来越像应用,前端要处理的东西就会成倍增长:
- 更长的 JavaScript
- 更复杂的状态切换
- 更多局部更新
- 更强的交互连续性
- 更高的用户响应预期
这时候,原来那套“改完上传、顺手合一合文件”的办法就会越来越吃力。
因为前端不再只是静态页面外面的一层薄壳。
它开始变成:
应用本身的一大块运行时现实。
而一旦前端成了应用现实的一部分,代码量、资源量、迭代频率、性能压力、协作成本就会一起长上来。
这也是为什么前端工程化真正大规模长出来,不是在最早网页时代,
而是在网页开始应用化之后。
07|所以前端工程化的真正起点,并不是“有了某个工具”,而是“同一份代码第一次必须同时服务两个世界”
这是第一篇最想立住的一层。
很多人回头讲前端工程化,总爱从工具名字开始讲:
GruntGulpwebpackVite
这当然没错。
但如果只从工具开始讲,你会很容易误以为:
工程化只是工具作者发明出来的一种开发者偏好。
更底层的现实其实是:
前端先出现了“双重现实”,工具才跟着长出来。
这两个现实分别是:
开发现实:
- 希望文件拆得细
- 希望结构清楚
- 希望修改局部不牵全身
- 希望调试尽量直接
交付现实:
- 希望请求尽量少
- 希望体积尽量小
- 希望缓存更稳定
- 希望线上资源更可控
只要这两个现实开始长期同时存在,
前端就迟早会需要一层中间机制,去负责把“源码世界”翻译成“上线世界”。
而这层中间机制,就是后来所有前端工程化工具链共同继承的祖先问题。
08|所以第一阶段真正发生的,不是“前端已经拥有成熟工程体系”,而是“它已经不可能再长期靠纯手工过日子”
这句话很重要。
因为第一篇如果讲得太猛,很容易把历史说歪。
我们不能说:
“前端从这时起就已经拥有了今天意义上的工程体系。”
这不对。
更准确的说法应该是:
到这一步,前端还没有成熟工程体系,但它已经被逼到不能长期只靠纯手工交付。
为什么?
因为手工办法的几个问题会越来越明显:
- 容易漏步骤
- 难以复现
- 难以团队协作
- 难以在项目变大后稳定维护
你可以偶尔手工合并文件。
但你没法长期把“每次发布都手工拼装资源”当成稳定制度。
一旦项目变大、人员变多、发布频率上升,这套办法就会迅速崩。
所以从历史位置上看,这一阶段真正完成的,不是“工程化已经成熟”。
而是另一件更关键的事:
前端第一次被现实逼到承认:开发和交付之间,已经需要一条正式流水线。
09|为什么前端工程化的起点,不是高级,而是手工已经扛不住了
把前面这些线叠一起看,第一篇最重要的判断可以压成一句:
前端工程化最早不是为了高级,而是为了让前端别再继续靠手工把开发态硬拧成交付态。
这句话里面有三层意思。
第一,工程化不是从“工具崇拜”开始的。
第二,它最早解决的是非常现实的交付问题。
第三,它的根子不是配置,而是开发现实和上线现实开始分裂。
所以理解前端工程化的起点,最不该记住的,不是某个具体工具是什么年份发布。
更该记住的是:
在工具真正出现之前,前端其实已经先有了工程化问题。
只是那时,大家还在用非常原始的办法和它搏斗。
10|前端工程化不是凭空出现的,它是网页长重之后的必然结果
前端工程化江湖的第一篇,最值得记住的,不是“早期前端没有工具”这种表层事实。
更值得记住的是:
它最初之所以看起来不需要工程化,不是因为前端天然轻,而是因为网页当时还没长到必须被工程化。
而一旦网页开始应用化,代码开始膨胀,性能开始反过来规定资源交付方式,
前端就会不可避免地撞上一道门槛:
源码世界和上线世界,不再是同一个世界。
所以第一篇如果只记一句,就记这句:
前端最早并不是工程化出来的,它只是慢慢被页面规模、性能压力和网页应用化这几股力量,一步步逼到再也不能只靠手工把开发态硬送上线。
编者注(事实核对):文中关于早期前端以 <script> 标签和手工组织资源为主的叙述,主要依据 webpack 官方 Why webpack 与早期 Motivation 文档中对 bundler 之前浏览器侧 JavaScript 组织方式的回顾,其中明确提到“脚本逐个引入”与“大单文件”这两种都难以扩展的现实。关于性能压力如何把“减少请求数”“合并脚本”“压缩资源”推成前端交付常识,主要依据 Yahoo! Exceptional Performance 团队的性能规则与 Steve Souders 对 Make Fewer HTTP Requests、Minify JavaScript 等规则的说明。关于网页应用化带来的历史拐点,主要依据 Jesse James Garrett 在 2005 年 Ajax: A New Approach to Web Applications 中对 Web application 形态转变的概括,以及 MDN 对 SPA / History API 历史背景的说明。正文将这一阶段概括为“前端被逼出构建需求”,属于基于脚本组织、性能优化和应用化压力共同叠加后的历史判断。
关键人物速览
- Jesse James Garrett:
Ajax这一说法的提出者。理解网页为什么会从“页面”一路长成“应用”,绕不开他。 - Steve Souders:早期 Web 性能实践的重要传播者。理解“减少请求、合并资源、压缩体积”为什么会变成前端交付常识,绕不开他。
- Ben Alman:
Grunt的发起者。理解为什么前端后来会把这些原本手工做的交付动作正式流水线化,下一篇就会接到他。
参考与延伸阅读
Why webpack
https://webpack.js.org/concepts/why-webpack/webpack Motivation
https://github.com/webpack/docs/wiki/MotivationBest Practices for Speeding Up Your Web Site - Yahoo Developer Network
https://developer.yahoo.com/performance/rules.htmlRule 1 - Make Fewer HTTP Requests
https://stevesouders.com/examples/rule-min-http.phpAjax: A New Approach to Web Applications
https://hotway.s3.us-east-1.amazonaws.com/ajax/Ajax%20-%20A%20New%20Approach%20to%20Web%20Applications.pdfMDN: Working with the History API
https://developer.mozilla.org/en-US/docs/Web/API/History_API/Working_with_the_History_APIMDN: Hash routing
https://developer.mozilla.org/en-US/docs/Glossary/Hash_routing
下篇预告:Grunt / Gulp 为什么会先火,因为前端第一次决定不再手工做那些重复又脏的交付动作。