灵魂拷问

  • 那前端各种产物(HTML、JS、CSS、IMAGES 等)应该用什么缓存策略?
  • 若使用协商缓存,但静态资源却不频繁更新,如何避免协商过程的请求浪费?
  • 若使用强缓存,那静态资源如何更新?
  • 配套的,前端静态资源应该如何组织?
  • 配套的,自动化构建 & 部署过程如何与 CDN 结合?
  • 如何避免前端上线,影响未刷新页面的用户?
  • 刚上线的版本发现有阻塞性 bug,如何做到秒级回滚,而非再次部署等 20 分钟甚至更久?
  • 如何实现一个预发环境,除了前端资源外都是线上环境,将变量控制前端环境内?
  • 部署环节如何方便配套做 AB 测试等?
  • 如何实现一套前端代码,发布成多套环境产物?
  • 如何实现按 feature 发布产物供用户使用,并逐步扩大 feature 灰度,将影响减到最小(即线上同时存在多 feature 产物)?
  • CDN 域名突然挂了,如何实现秒级 CDN 降级修补而非再次全部业务重新部署一次?

静态资源的部署和缓存问题
秒级回滚
多环境产物构建
灰度部署

静态资源组织

简单部署

image.png
只需要将这三个产物上传到服务器,通过Nginx访问index.html即可访问。
产生问题:用户每次访问都会向服务器请求 foo.css, bar.css 等静态文件,即使该文件并无变更。对带宽甚是浪费,对页面首屏性能等也有影响。

那么如何通过缓存来提升页面访问的效率?

协商缓存

一种策略是浏览器先问问服务器有没有变化,没变化就用旧资源。毕竟”问一问”的通信成本,远小于每次重新加载资源的成本

image.png

注:协商缓存一般可在服务端通过设置 Last-Modified、ETag 等 ResponseHeader 实现。
注:304 状态码,表示资源未发生变更,可使用浏览器缓存。

通过协商缓存,我们大幅优化了资源未变更时的网络请求,节约大量带宽,
问题:如果有成百上千个文件,就要协商成百上千次,显然还有优化的空间。

强缓存

强缓存:浏览器不会向服务器发送任何请求,直接从本地缓存中读取文件并返回Status Code: 200 OK。
image.png
此时,设置强缓存后,Network 大致变成了这样:
image.png

From DiskCache:从硬盘中读取。
From MemoryCache:从内存中读取,速度最快。
注:强缓存一般可在服务端通过设置 Cache-Control:max-age、Expires 等 ResponseHeader 实现。

问题:然而问题很快就来了,都不让浏览器发请求,但缓存还未到期我们发现有 bug,想更新 foo.css 怎么办?
又想设置尽量长的时间走缓存,又想要能随时更新?

缓存更新

通过精准控制将文件内容与版本号(URL)绑定,添加URL,我们可以称这种这个方式为 query-hash,后续发版上线时,只有被变更文件的 URL 会更新,实现了精确的缓存控制。
image.png