浏览器缓存是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览。

浏览器缓存设置是由服务器端生成的

浏览器通过置身机制判定服务器返回的请求头【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值,所以导致静态文件被缓存