缓存策略

/ 前端 / 2 条评论 / 498浏览

缓存简述

1.概念

每当我们输入网址时浏览器负责通过http协议向服务器请求获取数据,缓存可以缩短请求时间,节省带宽,对于缓存文件重复利用,利用缓存机制可以提升优化性能和体验。请求资源可以分为如下三步:发起网络请求,后端服务器处理,浏览器响应。缓存则是在第一次请求时将请求到的资源进行本地保存,下次发起同样请求时如果缓存策略判定本地资源和服务器资源一致,则浏览器直接读取缓存资源渲染给用户。

2.缓存位置

  1. ServerWorker是运行在浏览器背后的独立线程,用于实现缓存功能,使用ServerWorker时传输协议必须是HTTPS,可以自由控制缓存文件,如何匹配,并且缓存资源是带有持续性;
  2. MemoryCache内存缓存,文件储存于内存读取较快,但是缓存持续时间短,进程标签页被关闭时内存中的缓存将被释放;
  3. DiskCache硬盘缓存,读取数据较慢,根据HTTP请求头字段判定资源是否缓存;
  4. PushCache推送缓存,属于HTTP/2规范内容;

3.请求缓存场景

浏览器和服务器的通信方式是应答模式,是否有这样的疑惑,浏览器发起HTTP请求时如何确定资源是否已经缓存,如何进行缓存?解惑的具体流程:

每次请求资源都会优先查询浏览器是否存在缓存,存在则查看缓存标识信息;每次从服务器请求到资源后都会将资源建立缓存,所以浏览器的缓存机制是关键。

缓存分类

1.强缓存

不向服务器发送请求,直接读取缓存资源,打开F12控制台NetWork可以查看请求资源对于的信息status code:200 (from memory cache),强缓存可以通过Expires和Cache-Control进行实现。

Expires

缓存过期时间,字段信息来源于服务器的响应头,Expires=max-age+请求时间,服务器响应告诉浏览器在Expires过期之前不需要请求服务器,直接请求缓存资源。

Cache-Control

HTTP/1.1中,Cache-Control是最重要的规则,用于控制网页缓存,设置Cache-Control:max-age=300代表资源五分钟内同样的资源请求直接命中缓存资源,不需要请求服务器,属于命中强缓存,Cache-Control存在与请求头和响应头,并且可以组合使用指令,具有一下指令规则:

指令作用说明
public表示资源响应过程中可以被客户端和代理服务器缓存
private资源响应式仅客户端浏览器可以缓存
max-age=30资源缓存时间30毫秒(过期需要重新请求)
s-maxage=30仅在代理服务器中生效(优先级大于max-age)
no-store不缓存任何响应资源
no-cache资源可被缓存但需要同服务器上一致
min-fresh=3030毫秒内若资源过期则请求新资源(容忍最小新鲜度)
max-stale=3030毫秒内若资源过期则同样适用缓存(容忍最大过期时间)
  1. public,资源响应过程中经过的所有节点都可以缓存资源。很多时候资源会经过很多代理服务器(proxy),如果设置public值,请求资源时proxy服务器上的资源未失效则会直接返回给客户端;
  2. private,资源内容仅客户端可以缓存,Cache-Control的默认值,中间proxy服务器不会缓存,仅作为转发功能;
  3. no-cache,通过协商缓存来验证是否使用本地缓存资源;
  4. max-age,表示缓存资源失效时间;
  5. s-maxage,仅在代理服务器中生效,表示资源失效时间;
  6. max-stale=30,容忍的最大过期时间,表示客户端愿意接收一个30秒内被修改的过期文件;
  7. min-fresh=30,容忍的最小新鲜度,表示客户端不接收30秒内被修改的过期文件;

Cache-Control优先级高于Expires,Expires是远古时代的产物,现在常用于兼容写法,强缓存依赖于时间,而且精度也只能是毫秒级。如果服务器和客户端时间不一致则会导致缓存失效的问题。

2.协商缓存

当强缓存失效后就进行协商缓存,浏览器向服务器发送携带缓存标识(Etag和last-modified)的网络请求时,服务器会根据缓存标识处理,如果协商缓存生效则存在两个场景,304和NotModified两种情况;协商失败则返回200状态码和新请求的资源。

Last-Modified和If-Modified-Since

第一次请求支援时,服务器返回资源的同时,响应头中添加Last-Modified属性,表示服务器最后修改的时间,浏览器对资源文件进行缓存和响应头进行保存。下次请求时,浏览器检测到缓存中存在Last-Modified属性,于是在请求头中添加If-Modified-Since属性,这个属性值就是Last-Modified,服务器拿到If-Modified-Since进行比对,转换为时间戳,如果小于最后修改时间,则说明文件存在更新,返回200状态码和新的资源;如果没有更新则返回304和空的响应体,浏览器则直接从缓存读取。

Last-Modified存在如下弊端:

  1. 如果本地打开缓存文件即使没有修改也会造成Last-Modified变动,服务器匹对不上则导致返回相同的资源;
  2. 时间精度到秒,无法感知短时间内被修改的文件;

ETag和If-None-Match

Etag是服务器为当前资源建立唯一标识符,资源发生变动则Etag将会重新生成。浏览器请求资源时,服务器返回的响应头中存在Etag属性,下一次浏览器再次发起请求则会在请求头中添加If-None-Match属性且值为Etag,服务器检测到Etag并用于检测是否发生变化,如果发生变化则返回200和新的资源,否则返回返回304通知浏览器直接使用缓存的资源文件。

Last-Modified和Etag相比较不难发现,Etag在精度上优于Last-Modified,但在性能上Etag逊色于Last-Modified,若两者同时存在则优先考虑Etag。

缓存机制

强制缓存优先于协商缓存进行,协商缓存由服务器决定是否使用缓存,协商失败则请求新的资源文件,协商成功则返回304通知客户端使用本地缓存资源。

未设置缓存

如果什么缓存都没设置则浏览器会采用一个启发式的算法,通常取响应头中的 Date 减去 Last-Modified 值的 10% 作为缓存时间。

设置场景

  1. 频繁变动资源,使用Cache-Control:no-cache,每次请求都将进行协商缓存;
  2. 不常变化资源,Cache-Control: max-age=31536000设置一个超长的缓存时间,当请求相同URL被强缓存命中,文件名处添加打包后的hash值,解决资源变动而浏览器不请求的问题;
  1. 面试直接就有!太幸运了!

    回复
    1. @安格格

      能帮到你让我很开心

      回复