1997,那只蝴蝶飞过浏览器战争
古董级程序员,大厂出来后一直在创业公司,现在仍活跃在一线做 AI 相关开发。更完整的更新写在微信公众号「字与码」:工作经历、对新技术的想法,以及这些年折腾工具、模型和工程系统的记录,会不定期发在那里。
上一篇写到 1996 年,我说那一年屏幕还很小,世界刚刚变大。文章最后留下了一只蝴蝶:1997 年,我用 JavaScript 写过一个小程序,一只蝴蝶可以在页面上飞舞。
现在回头看,这件事小得不能再小。
它不是一个系统,不是一个项目,不是一个能上生产的产品,也不是一段值得放进简历的经历。它只是一个网页小动画。鼠标、窗口、脚本、图片、坐标、定时器,凑在一起,让一只蝴蝶在浏览器里飞来飞去。
但三十年后再想,我反而觉得那只蝴蝶比很多正式项目更像一个时代的标本。
因为它飞起来的时候,Web 还没有今天这么稳。HTML 是页面,JavaScript 是新鲜玩意儿,CSS 刚开始试图给网页一点像样的表现能力。浏览器厂商彼此不服,标准还在追赶现实,程序员写一个小动画,都可能要面对不同浏览器完全不同的脾气。
那只蝴蝶不是飞在一个成熟的平台上。
它飞在浏览器战争的缝隙里。
先让页面动起来
今天写一个网页动画很容易。CSS animation、requestAnimationFrame、Canvas、SVG、WebGL、各种框架和组件库,随便拿一个都能做出比当年复杂得多的效果。
1997 年不是这样。
那时你想让页面动起来,先要相信一件事:浏览器不只是文档阅读器。它可以执行脚本,可以响应用户,可以改变页面内容,可以把原本静止的 HTML 变成一个有行为的东西。
这个想法现在理所当然,当年却很新鲜。
我写那只蝴蝶,大概就是从最朴素的坐标开始。页面上有一个图片元素,脚本不断改变它的位置。为了让它看起来不是机械地横着走,还要给它一点上下浮动,一点速度变化,一点边界反弹。蝴蝶不是真的会飞,只是坐标不断变化,浏览器不断重绘。
可就是这种“假的飞”,让人第一次感到网页有了生命。

一只在早期浏览器窗口中飞舞的像素蝴蝶。图为按年代氛围生成的示意图。
这件事的技术含量,在今天看当然很低。可是当时真正让人费劲的,不是动画数学,而是浏览器差异。
同一段脚本,在一个浏览器里能跑,在另一个浏览器里可能不认。这个对象有,那个对象没有;这个属性这样叫,那个属性换了名字;这个事件能触发,那个事件行为又不一样。你要写判断,要试,要改,要在心里记住不同浏览器的怪癖。
很多年后,前端工程发展出一整套工具链:兼容层、构建工具、Polyfill、Babel、框架、测试、打包、组件化。它们看起来很现代,但根子上解决的仍然是同一个问题:Web 是开放的,开放就意味着差异;Web 是开放的,开放也意味着没有谁能彻底控制它。
1997 年的程序员还没有这些成熟工具,只能手工对付差异。
所以那只蝴蝶飞得并不轻盈。
它每飞一下,背后都有一堆 if。
DHTML:网页第一次想做应用
1997 年,浏览器大战已经不是口号,而是每个网页作者都能直接感受到的现实。
Netscape 仍然很强。Microsoft 则用 Internet Explorer 快速追赶,并且把浏览器和 Windows 生态更紧密地绑在一起。那年 Netscape Communicator 4 发布,Internet Explorer 4 也发布。两个浏览器都在告诉开发者:页面不应该只是展示内容,它应该能动、能变、能响应。
那时有一个词很流行:DHTML,Dynamic HTML。
DHTML 不是一项单独技术,更像一个组合称呼:HTML、CSS、JavaScript,再加上浏览器提供的页面对象模型。它承诺的东西很诱人:不用每次都重新加载页面,也能改变页面上的内容、样式和位置。
现在听起来,这不就是前端开发的基本常识吗?
但在 1997 年,它像一扇门刚刚打开。网页开始从“排版后的文档”变成“可以交互的界面”。菜单可以展开,图片可以移动,文字可以变色,窗口可以响应鼠标。页面不再完全依赖服务器返回一整份新 HTML,它开始在客户端自己做一点事情。
这就是后来 Web App 的影子。
当然,DHTML 的早期并不优雅。Netscape 有自己的层模型,Microsoft 有自己的 document.all。标准 DOM 还没有成为大家共同遵守的日常。你要做一个跨浏览器效果,常常不是“查文档然后实现”,而是“试出来一条能活的路”。
这种感觉很像在一座尚未竣工的大桥上走路。桥的方向是对的,但脚下有些木板还没有钉牢。
我那只蝴蝶就是在这样的桥上飞的。
它的意义不是动画本身,而是它让我开始意识到:程序员面对的运行环境正在从“我的机器”变成“用户的机器”,从“确定的系统”变成“复杂的生态”。
这和 1996 年的汇编经验完全不同。
写汇编时,世界很硬。指令、寄存器、内存地址,错就是错。Web 则软得多。浏览器版本、用户设置、屏幕大小、网络状态、厂商实现,都会影响你的代码。你不再只和机器对话,也在和标准、商业公司、用户环境对话。
这对后来写软件的人来说,是一次性格训练。
拨号时代的速度
如果只谈浏览器和脚本,很容易忘记 1997 年还有一个更基础的现实:网络很慢。
那时上网不是打开电脑就有。你要拨号,听见调制解调器发出一串古怪的声音,等待连接建立。电话线被占用,家里有人拿起电话,连接可能就断了。网页不是瞬间打开,图片需要一点点显示出来。下载一个软件,常常要计算时间,也要祈祷中途不要断。

US Robotics 56K 调制解调器。图片来源:Wikimedia Commons。
这种速度会改变开发习惯。
今天我们经常抱怨前端包太大、页面首屏慢、接口返回慢,但多数时候这种“慢”是体验问题。拨号时代的慢更具体,也更有压迫感。每一张图片、每一个脚本、每一次请求,都有真实代价。
所以那时的网页通常很克制。图片不能太大,脚本不能太重,页面结构也不能太复杂。你会天然关注文件大小,会愿意为了少几个 KB 做取舍。后来宽带普及、CDN 普及、移动网络普及,前端资源越来越大,工程系统越来越复杂。可是每隔几年,行业又会重新想起“性能”这件事。
这很有意思。
技术的资源变多以后,软件总会把资源重新吃满。然后下一代程序员再重新学习节制。
拨号时代教给人的,不只是等待,还有尺度感。
标准开始给混乱命名
1997 年还有一件看起来不热闹、但影响极深的事情:ECMA-262 第一版通过,ECMAScript 标准正式出现。
很多人后来会问:JavaScript 和 ECMAScript 到底是什么关系?
简单说,JavaScript 是大家熟悉的语言名字,最早来自 Netscape;JScript 是 Microsoft 的实现;ECMAScript 则是为了让这门语言有一个可标准化的共同基础。浏览器厂商可以竞争,但开发者不能永远被厂商差异撕裂。语言需要一份规范,哪怕一开始并不完美。
1997 年的 ECMA-262 第一版,就像给混乱起了一个正式名字。
当然,标准不会一夜之间让世界变好。现实里的浏览器兼容问题还会持续很多年。前端开发者后来会经历 IE6,会经历各种盒模型问题,会经历 DOM 差异,会经历无数调试到怀疑人生的夜晚。
但有标准,总比只有厂商实现要好。
标准的意义往往不是立刻解决问题,而是给所有人一个共同方向。没有它,开发者只能追着厂商跑;有了它,厂商至少要解释自己为什么不一样。
这是 Web 能活下来的关键之一。
开放标准让 Web 变得混乱,也让 Web 变得顽强。它不像某个封闭平台那样整齐,但它可以跨系统、跨设备、跨公司、跨时代。1997 年的 JavaScript 还很粗糙,可它最终变成了世界上最重要的编程语言之一,原因不只是语言设计本身,而是它长在了浏览器这个入口上。
入口改变命运。
语言也是如此。
小程序里的大时代
后来我做过很多比那只蝴蝶复杂得多的东西。
1998 年开始做 MIS。1999 年给银行做前置机,在 SCO UNIX 上真正在生产环境里写 socket。再往后做 Linux、做大厂平台、做微博大数据、做推荐、做图数据库、做 AI 工具。随便哪一段拿出来,工程复杂度都远远超过那只网页蝴蝶。
可复杂不等于更能代表时代。
那只蝴蝶小,但它站在转折点上。它告诉我,软件正在从“机器上的程序”变成“网络中的体验”。用户不再只是打开一个可执行文件,也会打开一个网址。程序不再只靠安装分发,也会通过浏览器抵达用户。交互不再只发生在桌面窗口里,也开始发生在网页里。
这件事影响后来所有软件。
企业系统会 Web 化,办公系统会 Web 化,邮箱会 Web 化,文档会 Web 化,开发工具也会 Web 化。今天我们在浏览器里写代码、开会、做设计、跑数据、使用 AI 工具,其实都可以从那时的方向里找到前因。
当年那只蝴蝶只是页面上的一个图片。
多年以后,整个软件行业都飞进了浏览器。
从确定性走向兼容性
1996 年的我还更接近底层。汇编、机器、内存、指令,这些东西给人的感觉是确定的。你只要足够理解机器,就能把问题追到底。
1997 年的 Web 则让我看到另一种现实:不是所有问题都能靠理解一台机器解决。
你需要理解用户环境,理解平台差异,理解厂商竞争,理解标准演进。你写的代码不再只运行在自己眼前那台电脑上,而是运行在别人桌上、别人浏览器里、别人网速下。你的控制力下降了,软件的边界扩大了。
这大概是很多程序员都会经历的一步。
刚开始写程序时,我们总想要确定性。后来工作越久,越会发现真正的软件工程是在不确定性里建立秩序。数据库会慢,网络会断,浏览器会怪,用户会误操作,需求会变化,依赖会升级,团队会换人。所谓工程能力,很大一部分就是在这些不稳定因素里,让系统尽可能稳定地工作。
那只蝴蝶教给我的,不是 JavaScript 语法。
它教给我的是:世界开始比代码大了。
下一年,蝴蝶落到表单上
1997 年的 Web 很兴奋,但真正能付钱、能落地、能让公司愿意投入的系统,很快会以另一种面貌出现。
1998 年,我开始做 MIS 开发。
那是另一个世界。没有蝴蝶,没有浪漫的浏览器战争,也没有“改变世界”的宏大叙事。更多的是表单、字段、数据库、报表、权限、流程、办公室里的电脑,以及用户每天真的要用的业务系统。
如果说 1997 年的蝴蝶让我看到网页可以动起来,那么 1998 年的 MIS 则让我看到软件如何进入组织内部,如何把纸面流程变成数据库记录,如何让一个公司开始用系统管理自己。
也是从那时起,Delphi 和 Borland 会变得重要。
下一篇,就写那些表单里的企业信息化。
1997 年 IT 大事记
- ECMA-262 第一版通过。 1997 年,ECMAScript 有了第一版标准。它给 JavaScript/JScript 这种浏览器脚本语言提供了共同基础。标准刚开始并不能立刻消灭兼容性问题,但它给后来 Web 前端的发展定下了一个方向:厂商可以竞争,语言本身需要有公共规范。
- Internet Explorer 4 和 Netscape Communicator 4 发布。 这两款浏览器把 DHTML、脚本、样式和页面对象模型推到更显眼的位置。网页从“文档”向“应用界面”靠近,但也把兼容性问题推得更尖锐。1997 年写一个网页动画,实际上就是在这两个浏览器世界之间找平衡。
- IEEE 802.11 标准获批。 第一版 Wi-Fi 标准在 1997 年获批。当时它还远不是大众消费级技术,但它把局域网从网线里解放出来。多年以后,无线网络会改变笔记本、手机、家庭路由器、办公室和公共空间,也会改变软件默认假设的使用场景。
- IBM Deep Blue 战胜卡斯帕罗夫。 1997 年 5 月,Deep Blue 在六局比赛中击败国际象棋世界冠军 Garry Kasparov。这不是今天意义上的大模型 AI,却是计算机智能进入公众视野的重要时刻。它让很多人第一次认真讨论:机器在某些智力任务上是否可以超过人。
- Steve Jobs 回到 Apple。 Apple 收购 NeXT 后,Jobs 在 1997 年回到 Apple,并逐步重新掌舵。这件事当时看起来是公司内部和产品线重整,后来却成为 iMac、Mac OS X、iPod、iPhone 这一整条路线的起点之一。
- Mac OS 8 发布。 Mac OS 8 在 1997 年发布。它不只是一次系统更新,也反映了 Apple 在经典 Mac OS 和后来 NeXT 技术路线之间的过渡期。这个过渡会在几年后走向 Mac OS X。
- Netflix 成立。 Netflix 在 1997 年成立时还不是流媒体公司,而是 DVD 邮寄租赁业务。它后来从物流和会员制开始,逐步走向在线视频和推荐系统,成为互联网改造传统行业的典型案例。
参考资料
- ECMA International:ECMA-262 ECMAScript Language Specification
- MDN:JavaScript 的历史背景
- Microsoft Internet Explorer 4 发布背景
- Netscape Communicator 4 发布背景
- DHTML 技术背景
- IEEE 802.11 标准背景
- IBM:Deep Blue 战胜 Kasparov
- Wired:Steve Jobs 在 1997 年重回 Apple
- Mac OS 8 发布背景
- Netflix 公司历史
- Wikimedia Commons:US Robotics 56K 调制解调器图片
微信公众号
欢迎关注「字与码」
如果这篇文章对你有用,也欢迎在微信里继续关注后续更新。