背景
在开发的过程中,很多时候会遇到发布的代码没有在浏览器上及时生效,场景:
测试:快来看,你这个bug没有改对
开发:是不是哦,强制刷新一下浏览器试试呢
测试:哦,对了...
但真实的用户怎么办?
基础知识
浏览器缓存位置
1.Service Worker (离线网页,PWA的核心技术)
2.Memory Cache(内存中的缓存)
3.Disk Cache(硬盘中的缓存)
4.Push Cache(推送缓存)
备注:2,3非常常见,1稍微要复杂一点,一些知名网站正在使用,如:淘宝,4没用过
浏览器缓存策略
1.强缓存:不会向服务器发送请求,直接从缓存中读取资源,会有如下状态:
2.协商缓存:强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存,会有如下状态:
备注:304表示虽然经历了服务器这一步,但该资源没有更新,于是继续使用缓存
解决方案
一、 文件名加hash值(最常见的方式)
如果你是用的现成的脚手架,如:vue-cli, create-react-app等,别人已经帮你做好了,基本不能遇到缓存的问题
二、文件名加不了hash值
在实际的项目开发中,就算我们是基于市面上流行的脚手架开发,也会遇到有一些js文件需要在index.html中直接用script标签引入,比如:config.js,里面写一些前端的配置,比如要访问的后台的服务地址等,方便运维部署的时候灵活设置,这样的文件就不方便加hash值了
对于这类文件往往有两种解决方式:
1.文件名加版本号,如:config-1.0.0.js,config-2.0.0.js,可参考jQuery
优点:可以对这类不常变的文件,设置长时间缓存,文件改变之后,升级版本号,这样既提高资源加载速度又能及时更新
缺点:文件名改变,index.html里面的引入也需要对应改变,对外提供的配置文件名不是固定的
2.nginx中配置,如
lcation /config.js {
add_header Cache-Control no-cache;
}
特定文件每次都向服务器请求,走协商缓存,注意:no-cache 是走协商缓存,no-store 才是不适用任何缓存
优点:对外提供的配置文件名统一
缺点:每次都会向后台请求,由后台判断是否使用缓存,速度肯定要比直接取本地的慢,但影响不大
注意:IE浏览器是一个奇葩的存在,以上方法不会作用于IE浏览器icon的更新,强制刷新也无效,只能用更换名字或者加版本号,如:
<link rel="icon" href="home2.png">
<link rel="icon" href="home.png?v=2">
个人建议:
如果你的文件很稳定,比如几个月,半年才修改一次,建议采用第1种
如果你的文件并不稳定,修改的频率很高,建议采用第2种
注意点
很多人可能会遇到这样的问题,既没有在客户端的请求中控制缓存,也没有在服务器的返回中控制,为什么浏览器还是会有缓存?
对于这类情况,浏览器默认会采用一个启发式的算法, 通常会取响应头的Date - Last-Modified值的10%作为缓存时间
Date 原始服务器消息发出的时间
Last-Modified 请求资源的最后修改时间
怎么理解呢,拿config.js来举个例子,比如当前刷新浏览器,向服务器请求时间为2019-06-06 01:29:55,这时服务器返回的Date为2019-06-06 01:30:00(假设客户端到服务器的时间为5秒),config.js最近修改的时间是2019-06-06 01:00:00,Last-Modified为2019-06-06 01:00:00,(Last-Modified - Date) * 10% = 3分钟,在未来的3分钟里,你无论刷新多少次,都会走强缓存,不会请求服务器
可以看出
1.一个资源越长时间不修改,缓存的时间就会越长
2.在我们在开发中,遇到缓存的bug,想要复现,用不停的修改资源文件的方式,却很难复现的原因
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。