浅析浏览器的缓存机制
由于公司没外网,好久没写技术博客了,几天无聊写一下浏览器缓存机制,以及如何禁止缓存。
个人理解:
浏览器第一次访问一个地址时会缓存静态文件(html,css,js),然后当第二次访问时会查看缓存是否过期,如果没有过期不会重新下载网页,直接使用缓存中的网页。只有网站明确标明已经更新了,浏览器才会重新下载网页。
HTTP缓存机制:
当浏览器向服务端发送请求或者下载静态文件时会根据Response Header里面的Cache-Control和expires两个属性来判断是否读取缓存中的数据,其中Cache-Control的优先级高。
Cache-Control对应的值:
Public:指示响应可被任何缓存区缓存。
Private:指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
no-cache:指示请求或响应消息不能缓存
no-store:用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
max-age:指示浏览器可以接收生存期不大于指定时间(以秒为单位)的响应。
min-fresh:指示浏览器可以接收响应时间小于当前时间加上指定时间的响应。
具体步骤:
①浏览器第一次访问服务器资源 /index.html
在浏览器中没有缓存文件,直接向服务器发送请求。
服务器返回 200 OK,实体中返回 index.html文件内容,并设置一个缓存过期时间,一个文件修改时间,一个根据index.html内容计算出来的实体标记Entity Tag,简称Etag。
浏览器将/index.html路径的请求缓存到本地。
②浏览器第二次访问服务器资源 /index.html
由于本地已经有了此路径下的缓存文件,所以这一次就不直接向服务器发送请求了。
首先,进行缓存过期判断。浏览器根据①中设置缓存过期时间判断缓存文件是否过期。
情景一:若没有过期,则不向服务器发送请求,直接使用缓存中的结果,此时我们在浏览器控制台中可以看到 200 OK(from cache) ,此时的情况就是完全使用缓存,浏览器和服务器没有任何交互的。
情景二:若已过期,则向服务器发送请求,此时请求中会带上①中设置的文件修改时间,和Etag
然后,进行资源更新判断。服务器根据浏览器传过来的文件修改时间,判断自浏览器上一次请求之后,文件是不是没有被修改过;根据Etag,判断文件内容自上一次请求之后,有没有发生变化
情形一:若两种判断的结论都是文件没有被修改过,则服务器就不给浏览器发index.html的内容了,直接告诉它,文件没有被修改过,你用你那边的缓存吧—— 304 Not Modified,此时浏览器就会从本地缓存中获取index.html的内容。此时的情况叫协议缓存,浏览器和服务器之间有一次请求交互。
情形二:若修改时间和文件内容判断有任意一个没有通过,则服务器会受理此次请求,之后的操作同①
服务端:
服务端通过If-Modified-Since(Last-Modified)和If-None-Match(Etag)这两个属性的值来判断缓存是否失效的。
Last-Modified/If-Modified-Since
Last-Modified/If-Modified-Since要配合Cache-Control使用。
Last-Modified:响应资源的最后修改时间。
If-Modified-Since:当缓存过期时,发现资源具有Last-Modified声明,则在请求头带上If-Modified-Since(值就是Last-Modified)。服务器收到请求后发现有头If-Modified-Since则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应HTTP 200整片资源内容(写在响应消息包体内);若最后修改时间较旧,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。
Etag/If-None-Match
Etag/If-None-Match也要配合Cache-Control使用。
Etag:资源在服务器的唯一标识(生成规则由服务器决定)。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。
If-None-Match:当缓存过期时,发现资源具有Etage声明,则在请求头带上If-None-Match(值就是Etag)。服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200或304。
前端控制禁止缓存:
1、在html 头部加上如下代码:
<META HTTP-EQUIV=”pragma” CONTENT=”no-cache”>
<META HTTP-EQUIV=”Cache-Control” CONTENT=”no-cache, must-revalidate”>
<META HTTP-EQUIV=”expires” CONTENT=”0″>
这样所有的js 文件都不会被缓存。
2、清楚form表单里的临时缓存
<body onLoad="javascript:document.yourFormName.reset()">
yourFormName :表单名字
其实form表单的缓存对于我们书写还是有帮助的,一般情况不建议清理,但是有时候为了安全问题等,需要清理一下!
3、清除ajax缓存
1.url地址上加上随机数
url参数后加上"?ran="+Math.random;//ran随便取
2、加上时间戳
"?timestamp=" + new Date().getTime();
服务端禁止:
在服务端加 header("Cache-Control: no-cache, must-revalidate")
参考:https://www.haorooms.com/post/js_llq_hc/
https://mp.weixin.qq.com/s?__biz=MjM5OTMxMzA4NQ==&mid=400875941&idx=2&sn=46101bbc366233024289492eaefa0e77&scene=21#wechat_redirect