baSpike 先生是best-experience公司的IT运营部门主管,
他的团队成功地通过利用 http-cache优化了前端工程。

Spike 将通过三个Scenario:

  • 通过配置http cache expire来消减访问压力,提高用户体验
  • 通过版本化强制失效本地的过期缓存
  • 通过内容摘要命名文件来更精确的控制缓存以及实现非覆盖式的发布

来展示他的团队是如何利用 http-cache并优化实施方案,以改善前端工程的。

第一个故事:我不想要那么多服务器和带宽

best-experience面临的资源访问压力和用户体验上的问题

随着best-experience提供的前端应用越来越强大,
Spike的压力也越来越大:

  • IT部门为了应对对静态资源的访问压力不断购置服务器和带宽。
  • 糟糕的用户体验使得用户转投竞争对手的网站。

工程师们刚刚通过应用Minify、AMD、打包、Gzip等手段优化前端页面的体验,
最终得到了如下图的一个资源引用关系:

“还是很多东西要下载啊,该那什么来拯救该死的延迟呢....”——Spike看着图想到。

Spike突然想起来:在早年间,流行的 yahoo 关于优化前端体验的35条建议和指导中,第三条是“Add an Expires or a Cache-Control Header”。yahoo 是这样描述这条建议的:

Web page designs are getting richer and richer, which means more scripts, stylesheets, images, and Flash in the page. A first-time visitor to your page may have to make several HTTP requests, but by using the Expires header you make those components cacheable. This avoids unnecessary HTTP requests on subsequent page views. Expires headers are most often used with images, but they should be used on all components including scripts, stylesheets, and Flash components.
Browsers (and proxies) use a cache to reduce the number and size of HTTP requests, making web pages load faster.

“这个正是我寻找的银弹”——Spike得意的笑了。
于是,Spike写下了第一个technology story。

作为IT 部门的老大:
我希望通过应用 HTTP缓存技术,对已经下载过的资源重用,消减用户在浏览页面时产生的不必要的http request。
以此,提高用户在浏览页面时候的体验,以及降低对于公司服务器的资源访问压力。

并找来了工程师Tom。

Expire 带来的美好生活

Tom刚刚参与了前一轮的优化工作,虽然成果显著,但是Tom 并不满足。
当Tom看到Jim 写下的Story时候,眼前一亮:
“这个方法,太赞了!!!甚至,我可以在登录页面底部,放置对其他页面资源的引用。提高用户在整个网站的浏览体验。”
——Tom的小宇宙瞬间爆发,很快就完成了新的优化方案。

best-experience的用户在接下来的时间里浏览页面,会这样下载资源,
以图片bgimage.png为例:

  • 用户第一次获取图片的时候,http request 如图:

  • 之后用户再次获取图片的时候,则完全从浏览器的缓存中读取数据了。

因为采用了http缓存方案,

  • 用户的feedback越来越好,访问量提高了;
  • IT部门也不用那么多服务器和带宽了。

财务总监邀请Spike共进晚餐,并谈起了自己在希腊的度假。
“我想我也应该去圣托里尼渡个假,犒劳下自己”——Spike美滋滋的想到。

第二个故事:失效缓存是个技术活

这个 BUG 我们明明修了啊!!!

一天,QA Tyke发现最近一轮发布的前端应用中没有包含很多新的feature。
Jerry 承诺说已经跟着这个月的release上线了,还测试过了。
经过前前后后的一番调查,Jerry发现浏览器一直在使用旧的缓存,而不是最新的版本。
Spike找来了 Jerry 和 Tom,三个人一起手动对引用的资源做了重命名做了紧急修复。

“真是没有银弹啊,我的圣托里尼啊!!”——Spike头疼的想到。

Spike、Jerry、Tom和Tyke坐在了一起,得出了新的结论:

  • 缓存前端工程中的资源时,需要考虑缓存有效期的问题
  • 虽然35条建议和指导中建议“Configure ETags”,但是很难确定静态资源缓存的有效期
  • 虽然Http缓存可以支持No-cache 或者 max-age =0的方式,保证浏览器每次都向服务器验证缓存有效性,但是这样会大大增加服务器的压力
  • 可以通过在资源引用上增加形如:<.... src="###.js?v=$version$">的版本化的方式,来强制浏览器更新缓存。

Spike写下了新的technology story

作为IT 部门的老大:
我希望在前端系统中,对引用的静态资源进行版本化管理。
使得即可以通过http缓存来提高用户体验,降低服务器压力;也可以使得用户即时获得更新后的资源。

“这都10月了,看来是去不成圣托里尼了,总觉得这个方案哪里有问题”——Spike忐忑不安。

用版本机制来保证浏览器更新资源

Jerry和Tom(很难想象他们两怎么配合的)终于在前端工程中实现了自动化的资源的版本化管理:

用户在最初访问页面的时候,会得到这样一个资源引用:

而当新的版本上线后,用户会得到这样一个资源引用:

第三个故事:更精确的缓存管理和平滑升级

(这个案例来自于知乎的大公司里怎样开发和部署前端代码? 张云龙的回答,前一个 story的内容有涉及)

每次更新后的尖峰时刻

11月的release后,运维人员 nibbles 找到 Spike
“这次上线了以后,服务器压力突然剧增,从GA上看用户花了很多时间在资源下载上”

Spike 找来了 Tom、Jerry、Tyke 和 nibbles 坐在了一起,分析原因:

“这是因为11月的部署完成后,前端应用引用的资源版本升级了,所有缓存失效导致的”——Tom 想了想说
“所有的资源引用?我还以为我们能精确到每一个文件的更新呢”——nibbles惊讶道
“如果单独标明每一个资源的版本,那么按照我们的实际情况来看,每次上线后访问压力就没那么大了”——Tyke
“我之前看webpack做到了”——Jerry兴致勃勃的谈了起来。
“他们采用的是文件摘要的方式,就是用 MD5对文件求值,如果两个文件是相同的,那么就求得同一个 hash 值;如果文件是不同的,就求得不同的 hash 值”——Jerry
“我们可以用这些文件的hash值作为版本号”——Jerry

“能不能通过文件名做版本管理,我希望知道哪些文件是这次部署要移除的,哪些是新增的”——nibbles
“这有什么问题么?”——Spike 很疑惑
“明年不是要做 CDN么?静态资源和页面文件会放置到不同的服务器上,很难做到页面文件和静态资源一同批次更新”——nibbles
(关于 CDN 和非覆盖部署式部署,请参考大公司里怎样开发和部署前端代码?前端工程之CDN部署
"恩,那么就这样吧,我回去写 story。"——Spike 一锤定音。
"还好,我们之前用了webpack,这就简单了"——Jerry

Spike写下了第三个story
作为IT 部门的老大:
我希望能用文件hash来命名静态资源文件,
使得可以按照文件来控制缓存和部署

"我觉得这回是最后一个Story了"——Spike 越来越乐观。

过渡到非覆盖式部署——大圆满?

如何应用 webpack的具体过程不再概述。

图片来源大公司里怎样开发和部署前端代码?


这样,nibbles 就可以很愉快的通过文件名比对,来分析每次部署变更的内容;
而best-experience未来上线的流程也会变为

  1. 先将新增的静态资源文件发布到静态资源服务器上
  2. 验证新的静态资源正确发布
  3. 服务器暂时离线,替换 html 文件等
  4. 删除无用的静态资源文件

“终于可以踏踏实实过圣诞节了”——Spike看着日历。

总结

Spike的总结

年底了,Spike在年终总结中写到:
以后在实施前端工程中,我们可以通过:

  • 配置永不过期的本地缓存——节约带宽,提高用户体验
  • 采用文件摘要作为缓存依据——更精确的缓存控制
  • 采用CDN——降低用户请求资源时候解析 DNS 的延迟
  • 利用文件摘要作为文件名——实现非覆盖式的部署,降低 down time

我的总结

我引用前端工程之CDN部署一文中对非覆盖式、缓存设计、CDN这些解决方案间的前因后果做的总结:

如果考虑到项目开发阶段,那么这将是更为复杂的软件工程问题。
在这个问题域中,还需要囊括文件压缩、合并、打包、重命名、目录设置等问题。
还好 gulp、webpack、fis、amd、requirejs这些工具及对应的插件能帮助到我们。(这些东东.....)
webpack提供了 hash、chunkhash、contenthash 以及社区提供的md5-hash。
当然这些都是关于工具的话题了,这次我们主要谈的是工程。
浅谈前端集成解决方案里提到了前端领域的8个技术元素与分类,挺有意思的。

再终——没有银弹

我们的 Spike先生来到了2月的北京旅游,放个带色的图:
我们自强不吸

在机场,Spike还是接到了Tyke的电话,“老爹啊,webpack那个文件摘要不准啊........”
“您好,因为天气原因,去往####的飞机延误,请您耐心等候........”
“.......”