浏览器:强缓存&协商缓存

466 阅读5分钟

大致看了网络上的几篇关于强缓存和协商缓存的文章,发现都写的不是很通俗易懂,这里我用一种比较易懂的语言去向大家解释什么是强缓存,什么是协商缓存及其工作流程,有错误请指出

强缓存

首先从字面意义来看,强缓存就是强制缓存的意思,浏览器为了减少对服务器的访问,将某些资源缓存到了本地,所以强缓存也叫做本地缓存。 它的主要工作原理是:

首先你要从服务器获取资源对吧,那么服务器会对这个资源设置一个过期时间,就是告诉你这个资源什么时候过期,一旦过期了就要像服务器重新请求这个资源,如果没过期,那你就要继续使用本地缓存的资源。这个就是强缓存的大致工作流程,就是你去请求资源时先看看本地资源有无过期,过期了再去麻烦服务器。

然后接下来看看服务器是怎么给资源设置过期时间的

在http1.0中,服务器会给响应头加上一个Expires属性,这个属性代表了资源过期的绝对时间(就是几月几号几点几分几秒的时候过期),值的大致形式是这样的:

Mar, 06 Apr 2020 10:47:02 GMT

然后在http1.1中新增了一个Cache-Control属性,字面上我把它理解为缓存控制器,这个属性告诉浏览器要怎么缓存这个资源,当然也有一些过期时间的设置,它的最主要的一个值是max-age,这个值代表了资源的有效期(意思就是资源能用多久)。然后还有其他几个常用的值:

  • no-cache:不使用本地缓存(即不适用强缓存)
  • no-store:直接禁止浏览器缓存数据(即每次请求这个资源都要向服务器请求)
  • public:代表该资源可以被所有用户缓存
  • private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。 以下是这个属性具体的使用例子,max-age=0代表立即过期

cache-control: no-cache, no-store, must-revalidate, private, max-age=0

当cache-control和expires同时存在时,浏览器会优先选择cache-control

好了以上就是强缓存的主要内容,下面看看协商缓存

协商缓存

协商缓存从字面意思来看就是浏览器跟服务器讨论要不要使用缓存的资源,当强缓存被浏览器跳过后(即强缓存的资源过期了),浏览器就要去和服务器商讨如何取得资源,这大致就是协商缓存的意思。具体的工作流程:

当浏览器第一次请求服务器资源时,服务器会返回一个附带资源缓存标识的资源给浏览器,当浏览器第二次去请求服务器这个资源时,就会先把那个标识给服务器,服务器就先检查这个资源缓存标识与服务器上面的资源缓存标识比较,如果不同,就代表资源有更新,此时就要返回资源,如果相同,则返回一个304状态码告诉浏览器资源没有更新,读取本地缓存的资源就可以了。 说白了就是利用一个标识来判别资源是否更新,当服务器上的资源更新了,标识也要更新,所以就会判别出不一样。以上就是协商缓存的大致工作流程

接下来看看这个缓存标识具体是什么。

在http1.0中,第一次请求服务器时,服务器就要返回一个名叫Last-Modified的缓存标识,这个从字面上就能理解,它保存的是资源上一次的修改时间,然后服务器就把这个给了浏览器保存,然后当浏览器再去请求服务器时,就要带上If-Modified-Since(存的就是Last-Modified)请求头去访问服务器,服务器再对比浏览器的Last-Modified和服务器上资源的Last-Modified,时间一致就返回304,不一致就返回新资源和新的Last-Modified

这种方式的弊端就是当服务器上的文件,删了一个字符,又添加回一个相同的字符,也会更新Last-Modified,但资源本身内容并没有改变,所以当下次请求过来时,就会返回同样的资源,而不是从缓存中读取资源

在 http 1.1 版本中,服务器通过 Etag 来设置响应头缓存标识。Etag 的值由服务端生成。在第一次请求时,服务器会将资源和 Etag 一并返回给浏览器,浏览器将两者缓存到本地缓存数据库。在第二次请求时,浏览器会将 Etag 信息放到 If-None-Match 请求头去访问服务器,服务器收到请求后,会将服务器中的文件标识与浏览器发来的标识进行对比,如果不相同,服务器返回更新的资源和新的 Etag ,如果相同,服务器返回 304 状态码,浏览器读取缓存。

对Etag的解释:

Etag的出现解决了几个Last-Modified的问题

  • 比如上面所说的,仅修改了文件时间但没有修改文件内容,此时我们并不希望客户端认为文件内容改变了而重新请求新的资源
  • 还有一点就是,某些文件的修改很频繁,比如一秒内修改了n多次,但Last-Modified的检测粒度是秒级的,所以如果文件内容修改了,却没有被Last-Modified检测出来,那Last-Modified自然保持不变,这也是我们不想看到的

最后上一个总的流程图,希望你看完我的文章后能更好的理解图的内容

image.png