浏览器缓存的解决方案
浏览器缓存的解决方案
——it唐伯虎
摘要:浏览器缓存的解决方案,包括传统前端和现代前端。
前言:本文只针对文件请求(html、css、js)进行分析,但不涉及json数据请求。
浏览器的状态
(1)当浏览器向服务器发起请求,如果请求正常,状态是200。
(2)浏览器接收到请求结果后,如果会根据响应头设置的缓存规则,把请求结果存起来。
(3)当浏览器再次发起相同的请求的时候,浏览器会先向服务器比对文件,只对比最后修改时间,如果最后修改时间变化就重新获取请求结果,此时状态是200;如果最后修改时间没有变化则从缓存读,此时状态是304。
(4)304状态是比较理想的缓存使用方案,但是往往来说,浏览器会走另一条粗暴的路线,即不进行时间比对,直接从缓存读,此时状态是200已缓存。
(200)> (304) > (200已缓存)
(10ms)>(5ms)> (0ms)
浏览器的刷新
(1)按f5刷新:
从缓存读取文件,然后将这些文件向服务器对比,如果最后修改时间变化就重新下载,此时状态是200,如果没变就从缓存读,此时状态是304,这是只理想情况,有些时候,只从缓存读取,状态是200已缓存。
(2)按ctrl+f5强制刷新:
强制删除当前页面的所有缓存,并且重新下载,此时状态是200。
(3)手动清除浏览器所有缓存:
强制删除浏览器的所有缓存,访问的时候重新下载,此时状态是200。
(4)在页面上点击链接、或者在地址栏输入、或者从浏览器书签进入,等等的大多数途径,
浏览器只从缓存读取,此时状态是200已缓存。
综上所述,需要清缓存的情况是第4点,其次是第1点的后半段。
改进方案
(1)css、js
这两种资源是由html指定调用的,只要html里指定的css、js链接变化了,浏览器就会加载新的css、js。
传统前端的方案是手动加版本号
<link href="css/style.css?v=${code}">
<script src="js/front.js?v=${code}"></script>
${code}代表版本号,由freemarker或jsp进行赋值,如果版本号变化了,整个网站的所有css、js都会重新下载。
现代前端的方案是自动加版本号
app.a7dec7ac.js
chunk-4a91bce9.b219889e.css
这种方案依赖于webpack、gulp等打包工具,打包结果自带了hash值,这些hash值是根据文件的最后修改时间生成的,如果文件没改过,名字就不会变化,这种方案控制缓存更为精确。
(2)html
在css、js加上版本控制之后,已经能避开大多数情况下的缓存,但由于css、js是由html指定调用的,所以说,如果html被缓存了,浏览器依旧会去调用旧的css、js。其中,上文“浏览器的刷新”第4点就会走这条路线。
html的文件名是跟浏览器的地址相关的。html文件名是什么,用户在浏览器就需要输入什么。所以说,不能给html文件加上版本号。对于html文件,我们采取禁用缓存的方案:
传统前端,在后端给需要的html加上响应头
response.addheader("cache-control", "no-cache, no-store");
现代前端,在nginx给index.html加上响应头
location = /index.html {
add_header cache-control "no-cache, no-store";
}