最佳实践
上来先说结论,原因放在后面:
- index.html 不做缓存,每次请求都获取最新版本
- 使用 webpack 等 build 后的其他所有资源文件(包括 js、css 和图片等),都做强缓存(一个月打底,可以设置一年)
原因
强缓存和协商缓存在社区已经被写烂了,都知道是怎么回事,这里就不做详细解释了,这里解释下为什么说上面的是最佳实践。
我们知道协商缓存其实也向服务端发起了一个请求,只不过最后经过一系列验证,结果就是不传输具体内容了,但是验证的过程也给后端造成了一些开销,所以我们要尽量减少这种开销。
那么把前端资源都用作强缓存就是最好的处理办法了,但是又面临一个问题『前端发版怎么更新』
这时候我们需要注意 build 后的前端资源,现在各个脚手架默认都会把文件名字生成一段 hash 值
xxx.6ae44c4e.js
这种。原来我一直不明白这样的意义在哪,现在明白了。
首先 index.html 不做缓存,所以当我们发版以后浏览器会获取到最新的 index.html 文件,由于每次 build 之后生成的文件名字不同,index.html 引入的前端的资源就不同,旧的所有的资源文件包括 js、css 和图片等)都不会影响新发版的内容。
这样的话就做到了在不发版的情况下,每次刷新基本就一个 index.html 的资源还有一些接口请求,其余的全都是强缓存资源。发版之后可以立马更新,不会造成资源混乱。现在掘金和 segmentfault 都是采取的这种策略。
实践数据对比
和运维的同事商量了强缓存的优化,将 build 之后的 static 文件夹全部做了 add_header Cache-Control "max-age=30243600",也就是强缓存 30 天的设置。
经过测试发现,由协商缓存到强缓存后,有如下变化:
类型请求数实际传输资源大小传输完毕(Finish)DOMContentLoadedLoad协商缓存631168K2.00s447 ms717 ms强缓存63123K1.43s424 ms704 ms
结果分析
首先,请求数量是一样的,完全 Load 的时候差不多,Finish 的时间提升了 25%,传输的资源大小减少了 80% 以上,同时由于没有和服务端去进行协商,相当于对服务端也做了优化。这些都是在协商缓存的基础上做的优化对比,如果后端服务连协商缓存都没上的话,真的应该优化一下了。