说起缓存可谓是让程序员爱恨交加!我结合项目经验谈谈自己的一些见解。
在我们更新完已上线的项目后,用户浏览器显示的确实旧版的页面,没有及时获取到我们更新的资源,此时用户刷新一下页面,就得到了更新后的资源,又是为什么呢?
答案就是浏览器缓存
浏览器缓存是前端优化的一个重要问题,缓存可以带来很多好处:
(1)减少冗余的数据传输,节省宽带;
(2)减轻服务器的请求负担,有缓存就可以少向服务器发送请求,尤其是对于一些访问量很大的网站
(3)资源从缓存中读取,无需向服务器发送请求再等待返回,加快了客户端访问速度
但是缓存也同样给前端带来了一个很严重的问题,就是上面所说的项目更新的问题。如果项目更新了,用户浏览器读取的是缓存资源,虽说刷新或者清除浏览器缓存可以获取最新的页面,但是做开发常说的一句话叫做:要把用户当傻瓜一样对待,能少一步绝不多一步(冒犯了冒犯了,立马道歉)
浏览器缓存主要指http缓存,其机制是根据http报文的缓存标识进行相应操作。
浏览器有三级缓存原理
1.先查找内存,如果内存中存在,从内存中加载;
2.如果内存中未查找到,选择从硬盘获取,如果硬盘有,从硬盘加载;
3.如果硬盘中未查找到,那就进行网络请求,加载到的资源缓存到硬盘和内存;
如上常见情况就是我们打开控制台的Network发现资源加载情况是200 from disk cache,这很明显浏览器没有请求新的资源,那么有没有办法去解决这种情况?
浏览器缓存(强制缓存和、协商缓存也叫对比缓存)
1.强制缓存
见字明意,强制缓存就是用户第一次访问页面之后,浏览器将数据存在缓存之中,在过期时间之内,都不会请求服务器,是否使用强制缓存存在于资源是否过期,该过期时间从第一次请求服务器响应头中获取,如果在过期时间内,从缓存中读取,如果超出过期时间,则使用协商缓存
控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Control优先级比Expires高。
2.协商缓存
从字面上意思主在协商,在第一次请求服务器时,服务器会返回一个资源的缓存标识,一起存到浏览器的缓存数据库,第二次请求资源时,浏览器会首先将缓存标识发送给服务器,服务器处理标识是否匹配,如果不匹配表示资源有更新,服务器会将新数据和缓存标识一起返回浏览器;如果匹配,表示资源没有更新并且返回304状态码,浏览器读取本地缓存服务器中的数据
与协商缓存相关的字段是 Last-Modified/If-Modified-Since、Etag/IF-None-Match
Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304
缓存类型 | 获取资源形式 | 状态码 | 发送请求到服务器 |
---|---|---|---|
强缓存 | 从缓存取 | 200(from cache) | 否,直接从缓存取 |
协商缓存 | 从缓存取 | 304(Not Modified) | 否,通过服务器来告知缓存是否可用 |
用户操作 | Expires/Cache-Control | Last-Modied/Etag | |
---|---|---|---|
地址栏回车 | 有效 | 有效 | |
页面链接跳转 | 有效 | 有效 | |
新开窗口 | 有效 | 有效 | |
前进回退 | 有效 | 有效 | |
F5刷新 | 无效 | 有效 | |
Ctrl+F5强制刷新 | 无效 | 无效 |
如文章开头所属,代码更新到线上后用户浏览器不能自行更新,我们不能要求客户在系统更新后都进行一次缓存清理的操作。 到底该如何解决呢? 在资源请求的URL中增加一个参数,比如:js/mian.js?ver=0.7.1。这个参数是一个版本号,每一次部署的时候变更一下,当这个参数变化的时候,强缓存都会失效并重新加载