浏览器缓存机制

浏览器缓存(Browser Caching)是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览。
浏览器缓存主要有两类:强缓存:cache-control;Expires 和缓存协商:Last-Modified、If-Modified-Since;ETag、If-None-Match。

缓存的优势

浏览器启用缓存至少有两点显而易见的好处:(1)减少页面加载时间;(2)减少服务器负载;

缓存相关的首部

浏览器是否使用缓存、缓存多久,是由服务器控制的。准确来说,当浏览器请求一个网页(或者其他资源)时,服务器发回的响应的「响应头」部分的某些字段指明了有关缓存的关键信息。下面看下,HTTP报文中与缓存相关的首部字段:

浏览器缓存机制

浏览器缓存机制

根据上面四种类型的首部字段不同使用策略,浏览器中缓存可分为强缓存和协商缓存

强缓存:Expires(HTTP 1.0)

Expires是HTTP 1.0提出的一个表示资源过期时间的header,它描述的是一个绝对时间,由服务器返回,用GMT格式的字符串表示

缺点:Expires时间是相对服务器而言,无法保证和客户端时间统一。

强缓存:Cache-Control(HTTP 1.1)

针对上述 Expires 的问题,http1.1新增了 Cache-Control 来定义缓存过期时间,这是一个相对时间,在配置缓存的时候,以为单位,用数值表示,如:Cache-Control:max-age=315360000

  1. max-age(单位为s)指定设置缓存最大的有效时间,定义的是时间长短。 当浏览器向服务器发送请求后,在max-age这段时间里浏览器就不会再向服务器发送请求了。
  2. public 指定响应会被缓存,并且在多用户间共享。 也就是下图的意思。如果没有指定public还是private,则默认为public。
    浏览器缓存机制
  3. private 响应只作为私有的缓存(见下图),不能在用户间共享。如果要求HTTP认证,响应会自动设置为private。
    浏览器缓存机制
  4. no-cache 指定不缓存响应,表明资源不进行缓存
    但是设置了no-cache之后并不代表浏览器不缓存,而是在缓存前要向服务器确认资源是否被更改。因此有的时候只设置no-cache防止缓存还是不够保险,还可以加上private指令,将过期时间设为过去的时间(private, max-age=0, no-cache)。
  5. no-store 绝对禁止缓存,如果用了这个命令不会进行缓存,每次请求资源都要从服务器重新获取。
  • Cache-Control描述的是一个相对时间,在进行缓存命中的时候,都是利用客户端时间进行判断,所以相比较 Expires,Cache-Control 的缓存管理更有效,安全一些。

  • Expires和Cache-Control同时存在时,Cache-Control优先级高于Expires。

协商缓存:Last-Modified、If-Modified-Since

当浏览器对某个资源的请求没有命中强缓存,就会发一个请求到服务器,验证协商缓存是否命中,如果协商缓存命中,请求响应返回的http状态为304(Not Modified)。

Last-Modified缺陷
你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

  1. Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
  2. 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
  3. 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形。Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。

协商缓存:ETag、If-None-Match (HTTP 1.1)

为了解决上述Last-Modified可能存在的不准确的问题,HTTP 1.1 还推出了 ETag 实体首部字段。

强缓存与协商缓存的异同

不同点:强缓存不发请求到服务器,协商缓存会发请求到服务器。
共同点:如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据;

参考文献

前端优化:浏览器缓存技术介绍
一文读懂前端缓存