前端缓存/浏览器缓存机制

前端缓存/浏览器缓存机制

1. 缓存过程分析

浏览器第一次向服务器发起该请求后拿到请求结果后,将请求结果和缓存标识存入浏览器缓存,浏览器对于缓存的处理是根据第一次请求资源时返回的响应头来确定的。
在这里插入图片描述

  • 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
  • 浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中

2.浏览器缓存方式

浏览器中的缓存作用分为两种情况,一种是需要发送HTTP请求,一种是不需要发送。

(1)强缓存

  • 不会向服务器发送请求,直接从缓存中读取资源。

  • 通过相应的字段来进行检查:在早期,也就是HTTP/1.0时期,使用的是Expires,而HTTP/1.1使用的是Cache-Control

  • 强缓存判断是否缓存的依据来自于是否超出某个时间或者某个时间段,而不关心服务器端文件是否已经更新,这可能会导致加载文件不是服务器端最新的内容。

Expires
即过期时间(Expires=max-age +请求时间),存在于服务端返回的响应头中,告诉浏览器在这个过期时间之前可以直接从缓存里面获取数据,无需再次请求

Expires: Wed, 22 Nov 2019 08:41:00 GMT

Expires缺陷:Expires 是 HTTP/1 的产物,受限于本地时间,如果修改了本地时间,可能会造成缓存失

Cache-Control
它和Expires本质的不同在于它并没有采用具体的过期时间点这个方式,而是采用过期时长来控制缓存,对应的字段是max-age。Expires和Cache-Control同时存在的时候,Cache-Control会优先考虑。比如这个例子:

Cache-Control:max-age=3600

在这里插入图片描述

(2)协商缓存

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:

  • 协商缓存生效,返回304和Not Modified

在这里插入图片描述

  • 协商缓存失效,返回200和请求结果
    在这里插入图片描述

1.Last-Modified ( If-Modified-Since)

即最后修改时间。在浏览器第一次给服务器发送请求后,服务器会在响应头中加上这个字段。
浏览器接收到后,如果再次请求,会在请求头中携带If-Modified-Since字段,这个字段的值也就是服务器传来的最后修改时间。
服务器拿到请求头中的If-Modified-Since的字段后,其实会和这个服务器中该资源的最后修改时间对比:

  • 如果请求头中的这个值小于最后修改时间,说明是时候更新了。返回新的资源,跟常规的HTTP请求响应的流程一样。
  • 否则返回304,告诉浏览器直接用缓存。

2.ETag(If-None-Match)

ETag 是服务器根据当前文件的内容,给文件生成的唯一标识,只要里面的内容有改动,这个值就会变。服务器通过响应头把这个值给浏览器。
浏览器接收到ETag的值,会在下次请求时,将这个值作为If-None-Match这个字段的内容,并放到请求头中,然后发给服务器。
服务器接收到If-None-Match后,会跟服务器上该资源的ETag进行比对:

  • 如果两者不一样,说明要更新了。返回新的资源,跟常规的HTTP请求响应的流程一样。
  • 否则返回304,告诉浏览器直接用缓存

ETag与Last-Modified对比:

  1. 在精准度上,ETag优于Last-Modified。优于 ETag 是按照内容给资源上标识,因此能准确感知资源的变化。而 Last-Modified 就不一样了,它在一些特殊的情况并不能准确感知资源变化,主要有两种情况:
  • 编辑了资源文件,但是文件内容并没有更改,这样也会造成缓存失效。
  • Last-Modified 能够感知的单位时间是秒,如果文件在 1 秒内改变了多次,那么这时候的 Last-Modified 并没有体现出修改了。
  1. 在性能上,Last-Modified优于ETag,也很简单理解,Last-Modified仅仅只是记录一个时间点,而 Etag需要根据文件的具体内容生成哈希值。

另外,如果两种方式都支持的话,服务器会优先考虑ETag。

总结:

强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。
在这里插入图片描述

缓存位置

web缓存机制
​ 在chrome的开发者工具中,在network /Size一列中可以看见一些请求,如果在 这列中明确标明大小KB,B,说明这是一个网络请求,否则一般都会明确标明:from memory cache,from disk cache和from ServiceWorker.

优先级依次是:

  • Service Worker
  • Memory Cache
  • Disk Cache
  • 网络请求
    1、Memory Cache

​ 它是内存中的缓存,和硬盘中的缓存相对。几乎所有的网络请求资源都会被浏览器加入到memory cache中去,但由于数量大所以是个短期的存储过程。当浏览的TAB页关闭的时候就失效了。或者一个页面占用的缓存过多的时候会导致前面的TAB缓存还没关闭就失效了。

​ (1)preloader

​ 一般浏览器在打开网站的时候都是请求js/css,之后解析执行,然后再次解析下一个请求这样的穿行操作,那么现在,能不能一边解析js/css,一边请求下一个资源,这就是preloader所干的事。memory cache机制保证了一个页面中若有两个相同的请求的时候,(比如有两个相同href的)都实际上只进行一次请求。在匹配缓存的时候,除了会对他们的URL进行匹配。也会对他们的类型、CORS中的域名规则进行校对。比如在script中缓存的资源不能用在image图片类型的请求中,即使他们的src相同。

​ (2)从memory cache中获取缓存内容的时候,浏览器自动忽略max-age=0,no-cache这些头部配置。因为memory cache只是短时间使用,大部分生命周期只有一次。max-size意思也就是“不要在下次浏览时使用”,和memory cache不冲突。如果真的不想让一个资源进入缓存,即使一次都不想,就可以使用no-store。这样memory cache就不会存储它了

2、disk cache

​ 也叫HTTP cache,是存储在硬盘上的缓存,是持久存储的,实际存在于文件系统当中。允许相同资源跨会话,甚至站点进行使用。他会严格根据HTTP头部信息进行判断哪些资源缓存,哪些可用,哪些过期了需要重新发送请求。命中之后浏览器会从硬盘中去读取资源,虽然过程会比内存中读取慢但是比网络请求快很多。一般大部分的缓存都是来自disk cache。

3.Service Worker

​ 以上的缓存机制和读取,缓存以及失效的行为都是通过浏览器判断进行的,只能通过设置响应的头部告诉浏览器应该做什么。而Service Worker就是一种更直接的方式,这个缓存是永久的,即使关闭TAB或者是关闭浏览器都不能将其删除。只有以下两种情况才会将其删除:手动调用API:cache.delete(resource)或者容量溢出。会被浏览器清除。如果Service Worker没有命中,就会调用fetch()方法继续获取资源。虽然这个时候没有命中Service Worker缓存,用了网络请求,但是在Chrome中依然会被标记为from Service Worker。

4.请求网络

​ 如果前面的三个缓存都没有命中,那么就通过网络请求的方式获取。但是在获取完成之后,需要处理如何将这个资源放在缓存中去的问题:

根据Service Worker中的handle决定是否存入Cache Storage(额外的缓存位置)。
根据HTTP头部的相关字段决定是否存入disk cache
memory cache 保存一份资源 的引用

参考文章:

神三元 :能不能说一说前端缓存
浪里行舟 深入理解浏览器的缓存机制

猜你喜欢

转载自blog.csdn.net/HZ___ZH/article/details/109656621