参考链接: 浅析浏览器的缓存机制

浏览器第一次访问一个地址时会缓存静态文件(html,css,js),然后当第二次访问时会查看缓存是否过期,如果没有过期不会重新下载网页,直接使用缓存中的网页。只有网站明确标明已经更新了,浏览器才会重新下载网页。

HTTP缓存机制

HTTP 缓存机制主要在 HTTP 响应头中设定,响应头中相关字段为 Expires、Cache-Control、Last-Modified、Etag。

Expires

  1. HTTP 1.0 协议中的。简而言之,就是告诉浏览器在约定的这个时间前,可以直接从缓存中获取资源(representations),而无需跑到服务器去获取。
  2. Expires 因为是对时间设定的,且时间是 Greenwich Mean Time (GMT),而不是本地时间,所以对时间要求较高。

Cache-Control

  1. HTTP1.1 协议中的,因为有了它,所以可以忽略上面提到的 Expires。因为 Cache-Control 相对于 Expires 更加具体,细致。
  2. 就算同时设置了 Cache-Control 和 Expires,Cache-Control 的优先级也高于 Expires。
  3. Cache-Control 响应头中常用字段的具体含义:
  • max-age:用来设置资源(representations)可以被缓存多长时间,单位为秒;
  • s-maxage:和 max-age 是一样的,不过它只针对代理服务器缓存而言;
  • public:指示响应可被任何缓存区缓存;
  • private:只能针对个人用户,而不能被代理服务器缓存;
  • no-cache:强制客户端直接向服务器发送请求,也就是说每次请求都必须向服务器发送。服务器接收到请求,然后判断资源是否变更,是则返回新内容,否则返回304,未变更。这个很容易让人产生误解,使人误以为是响应不被缓存。实际上 Cache-Control: no-cache 是会被缓存的,只不过每次在向客户端(浏览器)提供响应数据时,缓存都要向服务器评估缓存响应的有效性。
  • no-store:禁止一切缓存(这个才是响应不被缓存的意思)。

浏览器的缓存类型

  1. 强缓存:不会向服务器发送请求,直接从缓存中读取资源。可以看到该请求返回200的状态码
  2. 协商缓存:向服务器发送请求,服务器会根据这个请求的request headwe的一些参数来判断是否命中协商缓存。如果命中,则返回304并带上新的response header通知浏览器从缓存中都区资源

强缓存有关的header:

  • response header里的过期时间,浏览器再次加载资源时,如果在这个过期时间内,则命中强缓存。
  • Cache-Control:当值设为max-age=300时,则代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存。
  • Expires和Cache-Control:max-age=*** 的作用是差不多的,区别就在于 Expires 是http1.0的产物,Cache-Control是http1.1的产物,两者同时存在的话,Cache-Control优先级高于Expires;在某些不支持HTTP1.1的环境下,Expires就会发挥用处。所以Expires其实是过时的产物,现阶段它的存在只是一种兼容性的写法

协商缓存有关的header:

ETag和If-None-Match:

  • Etag是上一次加载资源时,服务器返回的response header,是对该资源的一种唯一标识,只要资源有变化,Etag就会重新生成。
  • 浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器接受到If-None-Match的值后,会拿来跟该资源文件的Etag值做比较,如果相同,则表示资源文件没有发生改变,命中协商缓存。

ETag和Last-Modified的区别:

  1. 精确度上,Etag要优于Last-Modified。Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。
  2. Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
  3. 优先级上,服务器校验优先考虑Etag。

浏览器缓存过程

  1. 浏览器第一次加载资源,服务器返回200,浏览器将资源文件从服务器上请求下载下来,并把response header及该请求的返回时间一并缓存;
  2. 下一次加载资源时,先比较当前时间和上一次返回200时的时间差,如果没有超过cache-control设置的max-age,则没有过期,命中强缓存,不发请求直接从本地缓存读取该文件(如果浏览器不支持HTTP1.1,则用expires判断是否过期);如果时间过期,则向服务器发送header带有If-None-Match和If-Modified-Since的请求;
  3. 服务器收到请求后,优先根据Etag的值判断被请求的文件有没有做修改,Etag值一致则没有修改,命中协商缓存,返回304;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200;
  4. 如果服务器收到的请求没有Etag值,则将If-Modified-Since和被请求文件的最后修改时间做比对,一致则命中协商缓存,返回304;不一致则返回新的last-modified和文件并返回200;