浏览器系列 -- 浏览器缓存

285 阅读6分钟

什么是浏览器缓存?

浏览器缓存是指浏览器(客户端)在本地磁盘中对 访问过的资源 保存的副本文件

同一个会话过程中会检查这个缓存副本是否足够新,在 浏览器中的前进或后退 时,可以从浏览器缓存中拿出使用。通过减少服务器处理请求的数量,用户将获得更快的体验

缓存策略分类

强缓存【由浏览器来确定】

强缓存是指浏览器不需要向服务器发送HTTP请求的,自己决定要不要用

那如何决定要不要用/可不可以用呢?根据字段来判断

HTTP/1.0HTTP/1.1 当中,这个字段是不一样的。在早期,也就是 HTTP/1.0 时期,使用的是Expires,而 HTTP/1.1 使用的是 Cache-Control

Expires (过期时间)

Expires: Wed, 22 Nov 2019 08:41:00 GMT // 是一串时间字符串

缺点:服务端和客户端之间要是有时间偏差会造成差错 (对于服务器来说未过期但浏览器却认为过期了)

Cache-Control: max-age (有效期)

在HTTP1.1中,采用了另一种方式:在请求资源后服务器发来的响应头中的字段 Cache-Control 来控制缓存,它的其中一个值 max-age,可以理解为 有效期,它的值的单位是 秒,通过设置这个字段的值可以控制缓存存活的时间,在这个时间内缓存都可以用。比如这个例子:

  • Cache-Control: max-age = 3600

代表这个响应返回后在3600 秒之内可以直接使用缓存

另外Cache-Control还有其他字段,分别表示不同的意思

  • Cache-Control: public 客户端代理服务器都可以缓存
  • Cache-Control: private 客户端不缓存,只给指定的代理服务器缓存,换句话说就是:跳过当前的强缓存,发送HTTP请求,即直接进入协商缓存阶段
  • Cache-Control: no-cache 不进行任何形式的缓存
  • Cache-Control: s-maxage 针对代理服务器的缓存时间

如何判断命中强缓存

命中强缓存没有发起 http 请求,资源显示状态码返回为 200 (from memory cache),也有可能是(from disk cache)即为从硬盘中获取的缓存,时间会比从内存中获取得要慢,但 session 级别的缓存关闭窗口就没了。总的来说返回状态码为200(from cache)则为命中强缓存

查看方式:

image.png

image.png

当缓存资源过期时,就不命中强缓存,但过期并不代表缓存资源不可用,那应该怎么判断可不可以用呢?这个时候就进入第二道判断流程——协商缓存

协商缓存【由服务器来确定】

协商缓存与强缓存的最大区别就是:需要发送HTTP请求了,因为浏览器需要向服务器协商缓存是否已更新/可不可以用。也是有两个字段可以判断:

Last-Modified (上次修改时间) 和 If-Modified-Since 作比较

  1. 浏览器第一次请求该资源,服务器返回资源并携带Last-Modified这个字段
  2. 浏览器将该字段及值保存起来,下次请求进入协商缓存环节时携带If-Modified-Since字段,其值便是上次请求的Last-Modified字段的值
  3. 服务器拿到请求头中的If-Modified-Since的字段后,会和该资源的真实最后修改时间对比:
    • 如果请求头中的这个值小于最后修改时间,说明要更新了。返回新的资源,跟常规的HTTP请求响应的流程一样
    • 否则返回304,告诉浏览器直接用缓存资源

ETag (版本号) 和 If-None-Match 作比较

ETag我理解为文件资源的版本号,在服务器中,只要里面的内容有改动,这个值就会变

同理:

  1. 浏览器第一次请求该资源,服务器返回资源并携带ETag这个字段
  2. 浏览器将该字段及值保存起来,下次请求进入协商缓存环节时携带If-None-Match字段,其值便是上次请求的ETag字段的值
  3. 服务器拿到请求头中的If-None-Match的字段后,会和该资源的真实最后修改时间对比:
    • 如果两者相同则返回304,告诉浏览器直接用缓存资源
    • 如果两者不一样,说明要更新了。返回新的资源,跟常规的HTTP请求响应的流程一样。当然如果有找 CDN 代理商的话,还可以先去 CDN缓存 里面找资源

Last-Modified 和 ETag 对比

  • 精准度上: ETag 比 Last-Modified 更加精准,比如:
  1. 服务器编辑了资源但整体内容并无改变,这时该资源的缓存就失效了;
  2. Last-Modified 能够感知的单位时间是秒,如果在1秒内多次修改,那Last-Modified 将不能感知到
  • 性能上: Last-Modified 的性能比 ETag 好,因为前者只是一串字符串,而后者需要根据文件的具体内容生成哈希值

如何判断命中协商缓存

响应头的状态码为 304 则为命中协商缓存

image.png

如何寻找缓存

缓存位置有:

  • 离线缓存
  • 内存缓存
  • 硬盘缓存
  • 推送缓存

查找缓存优先级:离线缓存 > 内存缓存 > 磁盘缓存 > 推送缓存

离线缓存

Service Worker 是运行在 JS 主线程之外的子线程,其功能有:离线缓存、消息推送和网络代理等。其中的离线缓存就是 Service Worker Cache

内存缓存【放HTML、JS、小图片】

  1. 读取快
  2. 量少
  3. 持续性差——Tab页面关闭就没了

磁盘缓存【放CSS、大图片、大文件】

  1. 读取慢
  2. 量大
  3. 持续性很长——除非过期或不可用了,否则一直保存

推送缓存[HTTP2.0 新增]

  1. 联系到HTTP2的相关
  2. 国内很少用,资料很少
  3. 简单理解就是在浏览器请求资源之前服务器已经把一部分资源提前推送过来了

如何触发缓存

  1. 前进、后退、跳转、打开新窗口【缓存有效】
  2. F5 刷新【强缓存失效
  3. Ctrl + F5 刷新【全部缓存失效

参考文章

(1.6w字)浏览器灵魂之问,请问你能接得住几个?