下图为缓存读取的过程:
浏览器缓存(Brower Caching)是浏览器对之前请求过的文件进行缓存,以便下一次访问时重复使用,节省带宽,提高访问速度,降低服务器压力。HTTP设置缓存机制主要在http响应头中设定,可以告诉浏览器在约定的时间前,可以直接从缓存中获取资源,无需跑到服务器,响应头中相关字段Expires(Expires对时间设定,且时间是格林尼治时间而非本地时间)、Cache-Control、Last-Modified、Etag。
一般缓存分为强缓存和协商缓存
强缓存
是指可直接从本地获取,而无需向浏览器发起任何请求。像下面这种
- from memory cache:不访问服务器,一般已经加载过了资源且缓存到内存中,直接从内存中读取缓存。浏览器关闭后,数据将不存在,资源释放
- from disk cache: 不访问服务器,已经在之前的某个时间加载过该资源,直接从硬盘中读取缓存,关闭浏览器,数据依然存在,此资源不会随着该页面的关闭而释放掉。
以上两点,优先访问memory cache,然后亅disk cache ,最后是请求网络资源。
协商缓存
如果没有命中强缓存,浏览器会发送请求到服务器,请求会携带第一次请求返回的有关缓存header字段信息(Last-Modified/If-Modified-Since和Etag/If-Node-Match),由服务器根据请求中的相关header信息来比对结果是否协商缓存命中,如果命中,则服务器返回新的响应header信息更新缓存中的对应header信息,但是并不返回资源内容,它会告知浏览器直接从缓存中获取;否则返回最新的资源内容。
强缓存和协商缓存的header参数
强缓存
- Expires:过期时间,如果设置了时间,在此时间之前则本地缓存始终有效,这是http1.0时的规范;
- cache-control:max-age=number,http1.1时的header信息,主要利用该字段的max-age值来进行判断,它是一个相对值;资源第一次的请求时间和Cache-Control设定的有效期,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间进行比较,如果请求时间在过期时间之前,就能命中缓存,否则就不行;cache-control除了该字段之外,还有其余几个值
- no-cache:不适用本地缓存。需要使用协商缓存,咸鱼服务器确认返回的响应是否被更改,如果之前的响应存在ETag,那么请求就会与服务端验证,若资源未更改,则可以避免重新下载
- no-store:直接禁止浏览器缓存数据,每次用户请求资源,都会发送请求,下载获取完整的资源
- publick:可以被所有的用户缓存,包括终端及CDN中间代理服务器
- private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存
注意:如果cache-control与expires同时存在的话,cache-control的优先级高于expires
协商缓存
协商缓存是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识来进行通信,从而让服务端可以判断缓存资源是否可用。主要涉及两组值 ETag/If-None-Match
和 Last-Modified/If-Modified-Since
,如果响应头没有 ETag/Last-Modified 字段,则请求头也不会有对应的字段。
1、Last-Modified/If-Modified-Since,两者都是GMT格式的时间字符串,具体过程:
- 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上Last-Modified,表示这个资源在服务器上最后修改的时间
- 浏览器在此跟服务器请求资源时,在request的header上加上If-Modified-Since的header,这个header的值就是上一次请求返回时Last-Modified的值
- 服务器再次收到资源请求时,根据浏览器传来的If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。当返回304时,response header中也不会添加Last-Modified的header,因为资源未发生变化。
- 当浏览器收到304时,就会从缓存中加载资源。
- 如果协商缓存没有命中,浏览器就会直接从服务器加载资源,Last-Modified的header在重心加载的时候会被更新,下次请求时,If-Modified-Since会启用上次返回的Last-Modifie
2、Etag/If-None-Match 这两个值是由服务器生成的每个资源的唯一标识字符串,只要资源有变化值就会变化,判断过程与 Last-Modified/If-Modified-Since 类似,但是不一样的是,当服务器返回304时,由于ETag重新生成了,response header还是会把ETag返回,及时它没有变化
有了 Last-Modified 为什么还要 ETag 呢?
主要是解决几个问题:
- 文件周期性的更改,但是内容并未变化,这时候我们并不希望客户端认为文件被修改了
- 某些文件修改频繁,在毫秒级,If-Modified-Since能检查到的粒度是秒级的,无法做出修改判断
- 有些服务器不能精确地到文件的最后修改时间
这时,利用ETag能够更加准确地控制缓存,因为ETag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识,服务器会优先验证ETag。
补充:
使用强缓存时,浏览器不会发送请求到服务端,若在此期间资源发生了变化,如何更新?
需要更新页面中引用的资源路径,让浏览器主动放弃缓存,加载新资源
<link rel="stylesheet" href="a.css?v=1.0.0" />
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!