浏览器缓存机制

289 阅读3分钟

一、强缓存

强缓存表示不会像服务器发送请求,而是直接从缓存中拿到数据,打开开发者模式中的Network 可以看见status显示的是状态码是200,同时size里面显示的是from disk cache或from memorycache。强缓存可以通过设置HTTP的响应头为Expires和Cache-Control实现。

  1. Expires

    是HTTP1.0版本的缓存机制,比较古老,用来表示指定资源过期时间(服务器时间)。其使用的原理是请求服务器后,服务器会指定一个资源过期的时间,表示在此时间之前,缓存有效不需要重新请求,但是有一Bug就是当我们更改客户端的时间的时候,可能就会导致缓存失效。可以简单的用一个公式描述为:

    资源过期时间(服务器指定)< 当前时间(客户端指定)

  2. Cache-Control

    Cache-Control是HTTP1.1版本的产物,比较新,同样也是用来控制缓存资源,一般会通过设置一个最大过期时间max-age来进行使用它,同样也可以用一个简单的公式表示:

    缓存时间(客户端时间)+ max-age < 当前时间(客户端时间)

    同时 ,Cache-Control也可以组合多种指令。

Expires和Cache-Control其实主要作用基本相同,只不过是机制不同,一般来说会两个一起用到,但是Cache-Control的优先级会大于Expires。

二、协商缓存

协商缓存的状态码是304,其表示当发起请求后浏览器会携带缓存标识向服务器发起请求,由服务器来判断是否应用,当数据没有变化时,服务器就会返回304,并且在缓存中直接取数据;当数据发生变化时,服务器会返回200,并且同时返回相关数据。协商缓存也可以通过设置请求头为Last-Modified 和 ETag实现。

  1. Last-Modified和If-Modified-Since

    浏览器在第一次访问资源时,服务器返回资源的同时,在response header中添加 Last-Modified的header,值是这个资源在服务器上的最后修改时间,浏览器接收后缓存文件和header;浏览器下一次请求这个资源,浏览器检测到有 Last-Modified这个header,于是添加If-Modified-Since这个header,值就是Last-Modified中的值;服务器再次收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回304和空的响应体,直接从缓存读取,如果If-Modified-Since的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200。

    But Last-Modified 还是存在一些弊端:

    1.如果本地打开缓存文件,即使没有对文件进行修改,但还是会造成 Last-Modified 被修改,服务端不能命中缓存导致发送相同的资源

    2.因为 Last-Modified 只能以秒计时,如果在不可感知的时间内修改完成文件,那么服务端会认为资源还是命中了,不会返回正确的资源

  2. Etag和If-None-Match

    为了解决 Last-Modified的Bug,Etag主要是由服务端返回一个对应资源的唯一标识,标识由服务器制定,所以当下次请求资源的时候会将上一次返回的Etag值放到request header里的If-None-Match里,服务器只需要比较标识是否相同就可以了,如果相同,返回304和空对象,从缓存中读取数据;如果不同,返回200和新的数据。

Etag和Last-Modified的比较,Etag比较准确,Etag的优先级会高于Last-Modified,但是Etag的性能要低于Last-Modified,因为Last-Modified只需要存一个时间。

附一个手写的简版脑图。。。。。。。。:)

Time is fair, because it gives everyone 24 hours.