浏览器缓存是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览。
浏览器缓存设置是由服务器端生成的
浏览器通过置身机制判定服务器返回的请求头【cache-control,expires,last-Modified,ETag等】实现缓存,关键的请求头有cache-control,expires,last-Modified,ETag等。
浏览器缓存方式有两种(强缓存和协商缓存)
什么是强缓存:
客户端第一次问服务器要某个资源时,服务器丢还给客户端所请求的这个资源同时,告诉客户端将这个资源保存在本地,并且在未来的某个时点之前如果还需要这个资源,直接从本地获取就行了,不用向服务器请求。这种方式缓存下来的资源称为强缓存。
如何建立关系:
a.浏览器第一次跟服务器请求一个资源,服务器在返回这个资源时,在相应头部会加上Cache-Control:max-age=xxx(http1.0中是expries字段,同时出现使用cache-control),如下图:
b.浏览器接收到资源后,连同response header一起缓存下来;
c.浏览器再次请求同一个资源时,会先从缓存中找到这个资源,获取date(第一次资源返回的响应时间)和Cache-Control中的max-age并计算出一个有效期(date + max-age),然后再和浏览器请求时间比较最后判断是否命中缓存;
d.如果没有命中缓存,浏览器直接向服务器发起请求,Cache-Control会在重新获取到服务器返回资源时更新。
注意:命中强缓存时,浏览器同样会收到status=200的response,chrome中可通过size区分从服务器返回的资源还是强缓存获得的资源。
什么是协商缓存:
客户端第一次问服务器要某个资源时,服务器丢还给客户端所请求的这个资源同时,将该资源的一些信息也返回给客户端,告诉客户端将这个资源缓存在本地。当客户端下一次需要这个资源时,将请求以及相关信息一并发送给服务器,由服务器来判断客户端缓存的资源是否需要更新:如不需要更新,就直接告诉客户端获取本地缓存资源(304);如需要更新,则将最新的资源连同相应的信息一并返回给客户端。
如何建立关系:
1. 通过 Last-Modified & If-Modified-Since(缺点:无法精确到毫秒)
a.浏览器第一次请求一个资源,服务器返回了该资源时,会在response headers中加上Last-Modified,这个response headers表示这个资源在服务器上的最后一次修改时间;
b.当浏览器再次请求该资源时,会在request headers中加上If-Modified-Since,这个值即为上一次服务器返回的Last-Modified时间;服务器再次收到资源请求时,将If-Modified-Since时间和资源在服务器上的最后修改时间与对比,如果If-Modifid-Since与最后修改时间一致,则命中缓存,服务器返回304,浏览器从缓存中获取资源;
c.若未命中缓存,服务器返回资源同时,浏览器缓存资源的Last-Modified会被更新。
2. 通过ETag & If-None-Match(缺点:ETag本身需要消耗 CPU,而它的优先级比 Last-Modified 高,当它存在时服务器无论 Last-Modified 是否存在都会使用它判断,ETag在分布式系统中生成的值可能不一样,会导致缓存失效)
a.浏览器第一次请求一个资源,会在response headers中加上ETag(这个ETag是根据该资源生成的唯一标识,这个唯一标识是个字符串,只有服务器认为资源有变化且应该提供新的资源时才会改变ETag),浏览器将资源连同ETag一并缓存。
b.当浏览器再次请求该资源时,会在request headers中加上If-None-Match,该值即为第一次服务器返回的ETag值;
c.服务器收到资源请求后,会根据要请求的资源重新计算生成相应的ETag,然后与If-None-Match比较。对比结果一致即命中缓存,不一致则未命中缓存,返回资源同时将新的ETag。
如何清除缓存
1. 清除图片缓存:
通过前端变化,让js每次生成一个随机数作参数放在url后边
2. 清除js、css缓存:
a. 引入js、css文件时加个版本号,如果每次发布新的js代码,更新对应的版本号。
b. 如果内容较少可以通过script和style标签将js和css代码写到html页面中,但内容较多时不容易维护
3. 接口缓存:
在请求的接口后面加一个时间戳
4.清除页面
<meta http-equiv="Cache-control" content="no-cache,max-age=0, must-revalidate,no-store"> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Expires" content="0" /> <meta http-equiv="Cache" content="no-cache">
浏览器存在默认缓存行为,根据浏览器不同默认缓存不一样,火狐浏览器默认 【缓存时间=(访问时间-变更时间)/ 10 】
最新版本Nginx默认在resquest headers中返回Etag值,所以导致静态文件被缓存