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|于是最早长出来的,不是现代意义上的工具链,而是一批很朴素但已经很工程化的交付动作

很多人会把“工程化”理解得过于狭窄。

仿佛只有出现了 webpackViteBabel 这类名字,前端才算工程化。

其实不是。

更早的时候,虽然还没有今天这样的统一工具层,

但很多典型的工程动作已经出现了。

比如:

  • 开发时拆很多文件,发布时手工合并
  • 上线前把脚本压缩
  • 给静态资源开压缩和缓存策略
  • 把源码目录和发布目录分开
  • 人肉维护一个“开发版 / 线上版”的差异

这些动作看起来朴素,甚至土。

可它们已经在回答一个非常工程化的问题:

同一份前端代码,怎样从“便于开发”转成“便于交付”。

换句话说,前端工程化并不是突然从天而降的。

它最早是以一种很原始的形态出现的:

先把开发态和发布态区分开。

而只要这件事一发生,工程化其实就已经开始了。


06|网页应用化让这场矛盾彻底升级:从“页面里有点脚本”变成“页面本身越来越像应用”

如果说性能压力让前端第一次开始认真想“怎么交付”,

Ajax 和网页应用化,则让这件事彻底从边缘问题变成中心问题。

Jesse James Garrett 在 2005 年那篇著名文章里,把 Ajax 描述成一种“对 Web 应用的新方法”。

这句话的历史意义非常大。

因为它点明了一件后来几乎决定前端命运的事实:

网页不再只是被动展示的页面,而开始承受越来越多应用级交互。

一旦网页越来越像应用,前端要处理的东西就会成倍增长:

  • 更长的 JavaScript
  • 更复杂的状态切换
  • 更多局部更新
  • 更强的交互连续性
  • 更高的用户响应预期

这时候,原来那套“改完上传、顺手合一合文件”的办法就会越来越吃力。

因为前端不再只是静态页面外面的一层薄壳。

它开始变成:

应用本身的一大块运行时现实。

而一旦前端成了应用现实的一部分,代码量、资源量、迭代频率、性能压力、协作成本就会一起长上来。

这也是为什么前端工程化真正大规模长出来,不是在最早网页时代,

而是在网页开始应用化之后。


07|所以前端工程化的真正起点,并不是“有了某个工具”,而是“同一份代码第一次必须同时服务两个世界”

这是第一篇最想立住的一层。

很多人回头讲前端工程化,总爱从工具名字开始讲:

  • Grunt
  • Gulp
  • webpack
  • Vite

这当然没错。

但如果只从工具开始讲,你会很容易误以为:

工程化只是工具作者发明出来的一种开发者偏好。

更底层的现实其实是:

前端先出现了“双重现实”,工具才跟着长出来。

这两个现实分别是:

开发现实:

  • 希望文件拆得细
  • 希望结构清楚
  • 希望修改局部不牵全身
  • 希望调试尽量直接

交付现实:

  • 希望请求尽量少
  • 希望体积尽量小
  • 希望缓存更稳定
  • 希望线上资源更可控

只要这两个现实开始长期同时存在,

前端就迟早会需要一层中间机制,去负责把“源码世界”翻译成“上线世界”。

而这层中间机制,就是后来所有前端工程化工具链共同继承的祖先问题。


08|所以第一阶段真正发生的,不是“前端已经拥有成熟工程体系”,而是“它已经不可能再长期靠纯手工过日子”

这句话很重要。

因为第一篇如果讲得太猛,很容易把历史说歪。

我们不能说:

“前端从这时起就已经拥有了今天意义上的工程体系。”

这不对。

更准确的说法应该是:

到这一步,前端还没有成熟工程体系,但它已经被逼到不能长期只靠纯手工交付。

为什么?

因为手工办法的几个问题会越来越明显:

  • 容易漏步骤
  • 难以复现
  • 难以团队协作
  • 难以在项目变大后稳定维护

你可以偶尔手工合并文件。

但你没法长期把“每次发布都手工拼装资源”当成稳定制度。

一旦项目变大、人员变多、发布频率上升,这套办法就会迅速崩。

所以从历史位置上看,这一阶段真正完成的,不是“工程化已经成熟”。

而是另一件更关键的事:

前端第一次被现实逼到承认:开发和交付之间,已经需要一条正式流水线。


09|为什么前端工程化的起点,不是高级,而是手工已经扛不住了

把前面这些线叠一起看,第一篇最重要的判断可以压成一句:

前端工程化最早不是为了高级,而是为了让前端别再继续靠手工把开发态硬拧成交付态。

这句话里面有三层意思。

第一,工程化不是从“工具崇拜”开始的。

第二,它最早解决的是非常现实的交付问题。

第三,它的根子不是配置,而是开发现实和上线现实开始分裂。

所以理解前端工程化的起点,最不该记住的,不是某个具体工具是什么年份发布。

更该记住的是:

在工具真正出现之前,前端其实已经先有了工程化问题。

只是那时,大家还在用非常原始的办法和它搏斗。


10|前端工程化不是凭空出现的,它是网页长重之后的必然结果

前端工程化江湖的第一篇,最值得记住的,不是“早期前端没有工具”这种表层事实。

更值得记住的是:

它最初之所以看起来不需要工程化,不是因为前端天然轻,而是因为网页当时还没长到必须被工程化。

而一旦网页开始应用化,代码开始膨胀,性能开始反过来规定资源交付方式,

前端就会不可避免地撞上一道门槛:

源码世界和上线世界,不再是同一个世界。

所以第一篇如果只记一句,就记这句:

前端最早并不是工程化出来的,它只是慢慢被页面规模、性能压力和网页应用化这几股力量,一步步逼到再也不能只靠手工把开发态硬送上线。


编者注(事实核对):文中关于早期前端以 <script> 标签和手工组织资源为主的叙述,主要依据 webpack 官方 Why webpack 与早期 Motivation 文档中对 bundler 之前浏览器侧 JavaScript 组织方式的回顾,其中明确提到“脚本逐个引入”与“大单文件”这两种都难以扩展的现实。关于性能压力如何把“减少请求数”“合并脚本”“压缩资源”推成前端交付常识,主要依据 Yahoo! Exceptional Performance 团队的性能规则与 Steve Souders 对 Make Fewer HTTP RequestsMinify JavaScript 等规则的说明。关于网页应用化带来的历史拐点,主要依据 Jesse James Garrett 在 2005Ajax: A New Approach to Web Applications 中对 Web application 形态转变的概括,以及 MDN 对 SPA / History API 历史背景的说明。正文将这一阶段概括为“前端被逼出构建需求”,属于基于脚本组织、性能优化和应用化压力共同叠加后的历史判断。


关键人物速览

  • Jesse James GarrettAjax 这一说法的提出者。理解网页为什么会从“页面”一路长成“应用”,绕不开他。
  • Steve Souders:早期 Web 性能实践的重要传播者。理解“减少请求、合并资源、压缩体积”为什么会变成前端交付常识,绕不开他。
  • Ben AlmanGrunt 的发起者。理解为什么前端后来会把这些原本手工做的交付动作正式流水线化,下一篇就会接到他。

参考与延伸阅读

  1. Why webpack
    https://webpack.js.org/concepts/why-webpack/

  2. webpack Motivation
    https://github.com/webpack/docs/wiki/Motivation

  3. Best Practices for Speeding Up Your Web Site - Yahoo Developer Network
    https://developer.yahoo.com/performance/rules.html

  4. Rule 1 - Make Fewer HTTP Requests
    https://stevesouders.com/examples/rule-min-http.php

  5. Ajax: A New Approach to Web Applications
    https://hotway.s3.us-east-1.amazonaws.com/ajax/Ajax%20-%20A%20New%20Approach%20to%20Web%20Applications.pdf

  6. MDN: Working with the History API
    https://developer.mozilla.org/en-US/docs/Web/API/History_API/Working_with_the_History_API

  7. MDN: Hash routing
    https://developer.mozilla.org/en-US/docs/Glossary/Hash_routing


下篇预告:Grunt / Gulp 为什么会先火,因为前端第一次决定不再手工做那些重复又脏的交付动作。