
上一篇写到 1996 年,我说那一年屏幕还很小,世界刚刚变大。文章最后留下了一只蝴蝶:1997 年,我用 JavaScript 写过一个小程序,一只蝴蝶可以在页面上飞舞。现在回头看,这件事小得不能再小。它不是一个系统,不是一个项目,不是一个能上生产的产品,也不是一段值得放进简历的经历。它只是一个网页小动画。鼠标、窗口、脚本、图片、坐标、定时器,凑在一起,让一只蝴蝶在浏览器里飞来飞去。但三十年后再想,我反而觉得那只蝴蝶比很多正式项目更像一个时代的标本。因为它飞起来的时候,Web 还没有今天这么稳。HTML 是页面,JavaScript 是新鲜玩意儿,CSS 刚开始试图给网页一点像样的表现能力。浏览器厂商彼此不服,标准还在追赶现实,程序员写一个小动画,都可能要面对不同浏览器完全不同的脾气。那只蝴蝶不是飞在一个成熟的平台上。它飞在浏览器战争的缝隙里。先让页面动起来今天写一个网页动画很容易。CSS animation、requestAnimationFrame、Canvas、SVG、WebGL、各种框架和组件库,随便拿一个都能做出比当年复杂得多的效果。1997 年不是这样。那时你想让页面动起来,先要相信一件事:浏览器不只是文档阅读器。它可以执行脚本,可以响应用户,可以改变页面内容,可以把原本静止的 HTML 变成一个有行为的东西。这个想法现在理所当然,当年却很新鲜。我写那只蝴蝶,大概就是从最朴素的坐标开始。页面上有一个图片元素,脚本不断改变它的位置。为了让它看起来不是机械地横着走,还要给它一点上下浮动,一点速度变化,一点边界反弹。蝴蝶不是真的会飞,只是坐标不断变化,浏览器不断重绘。可就是这种“假的飞”,让人第一次感到网页有了生命。一只在早期浏览器窗口中飞舞的像素蝴蝶。图为按年代氛围生成的示意图。这件事的技术含量,在今天看当然很低。可是当时真正让人费劲的,不是动画数学,而是浏览器差异。同一段脚本,在一个浏览器里能跑,在另一个浏览器里可能不认。这个对象有,那个对象没有;这个属性这样叫,那个属性换了名字;这个事件能触发,那个事件行为又不一样。你要写判断,要试,要改,要在心里记住不同浏览器的怪癖。很多年后,前端工程发展出一整套工具链:兼容层、构建工具、Polyfill、Babel、框架、测试、打包、组件化。它们看起来很现代,但根子上解决的仍然是同一个问题:Web 是开放的,开放就意味着差异;Web 是开放的,开放也意味着没有谁能彻底控制它。1997 年的程序员还没有这些成熟工具,只能手工对付差异。所以那只蝴蝶飞得并不轻盈。它每飞一下,背后都有一堆 if。DHTML:网页第一次想做应用1997 年,浏览器大战已经不是口号,而是每个网页作者都能直接感受到的现实。