# 5、浏览器缓存

# 浏览器缓存位置

TIP

  • Memory Cache:内存缓存,窗口关闭就会消失
  • Disk Cache:磁盘缓存,也就是存储在硬盘中的缓存,读写速度慢,比Memory Cache胜在容量和存储时效性上。

浏览器有三级缓存原理

  • 1、先找内存,如果内存中存在,从内存中加载
  • 2、内存中未找到,再找硬盘,硬盘中存在,从硬盘中加载
  • 3、硬盘中未找到,进行网络请求,加载到的资源缓存到硬盘和内存中

# 浏览器会把哪些文件丢进内存中,哪些丢进硬盘中?

TIP

对于大文件来说,是不会存在内存中的,反之优先。 当前系统内存使用率高的话,文件优先存进磁盘中。

# 浏览器的缓存策略

通常浏览器的缓存策略有两种:强制缓存 和 协商缓存,并且缓存策略都是通过HTTP header来实现的。

# 强缓存

强缓存

当用户第一次访问页面之后,浏览器将数据缓存起来,在过期时间内,都不会请求服务器,而是直接去读取缓存中的内容。过期时间从第一次请求的响应头中获取。在过期时间内,从缓存中读取,超出过期时间,则会使用协商缓存。在chrome控制台的Network选项中可以看到请求返回200的状态码(灰色),并且Size显示 form disk cacheform memory cache

强缓存可以通过设置两种HTTP Header来实现:

  • Expires
  • Cache-control(优先级高于Expires)

# Expires

http1.0的产物,缓存的过期时间,用来指定资源的到期时间,是服务器端的具体时间点,浏览器发送请求时会根据系统时间和Expires的值进行对比,由于是和系统时间作比较,所以会有缓存有效期不准的问题(已不推荐使用)。也就是说,Expires = max-age + 请求时间,需要和Last-Modified结合使用。ExpiresWeb服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。

# Cache-Control

Cache-Control

http1.1的产物,控制缓存的行为,常用属性值如下:

  • max-age:单位为妙,多少秒后失效
  • no-cache:不使用强缓存,需要与服务器验证缓存是否新鲜
  • no-store:禁止使用缓存(包括协商缓存),每次向服务器请求最新的资源
  • private(默认值):专用于个人的缓存,中间代理、CDN等不能缓存此响应,max-age存在时则会验证是否过期
  • public:响应可以被中间代理、CDN缓存
  • must-revalidate:在缓存过期前可以使用,过期后必须向服务器验证

# Expires和Cache-Control的区别

最大的区别就是Expireshttp1.0的产物,而Cache-Controlhttp1.1的产物,两者同时存在的话Cache-Control优先级是高于Expires的。

强缓存判断是否缓存的依据来自于是否超出某个时间或某个时间段,而不关心服务器端文件是否更新。因此才有了协商缓存策略;

# 协商缓存

当强缓存失效后,浏览器携带缓存标识向服务器发送请求,由服务器根据缓存标识决定是否使用缓存。 协商缓存可以通过设置HTTP Header来实现:

  • Last-Modified
  • Etag(会优先验证Etag)

# Last-Modified 和 If-Modified-Since

TIP

浏览器在第一次访问资源时,服务器返回资源的同时,在response header中会添加Last-Modifiedheader,值为这个资源在服务器上最后的修改时间,浏览器接收后缓存资源和header

浏览器下一次请求时,当强缓存已过期,且检测到有Last-Modified这个header,就会在请求中添加If-Modified-Since这个header,值就是Last-Modified的值,服务器再次收到这个资源请求,就会根据If-Modified-Since这个值与服务器中这个资源的最后修改时间做对比,如果没有变化,就返回304、新的header和空响应体,直接从缓存中读取。如果资源修改了,就会返回新的资源和新的过期时间。

Last-Modified存在的弊端

  • Last-Modified只能以秒为单位计时,如果文件的修改频率在秒级以下,这样的话,Last-Modified就不再准确;
  • 有些文档可能会被周期性的重写,尽管内容没有发生变化,但Last-Modified会发生变化。

# Etag 和 If-None-Match

TIP

为了解决Last-Modified存在的弊端,HTTP1.1推出了EtagIf-None-MatchEtag是服务器响应请求时,返回当前资源的实体标签(由服务器生成,可以是文档的序列号或版本名,或者是文档内容的校验和及其他指纹信息),当发布者对文档进行修改时,可以修改文档的实体标签来说明这个新的版本,这样,缓存就可以用If-None-Match来检验资源是否被修改过。 浏览器在下次发送请求时,就会将Etag的值放在请求头headerIf-None-Match中。服务器会比对If-None-Match的值和该资源的Etag值是否一致,如果一致,说明未修改,返回304,浏览器继续使用缓存。如果不一致,返回200以及新的资源和EtagEtag 和 Last-Modified 用哪个? 给哪个用哪个,如果两个都给,则只有Etag不变,且Last-Modified与服务器一致的时候才能返回304 Not Modified;

browser-5-2

# 如果什么缓存策略都没设置,那么浏览器会怎么处理?

浏览器会采用一个启发式的算法,通常会取响应头中的 Date 减去 Last-Modified 值的 10% 作为缓存时间。

# 用户行为对缓存的影响

意思是用户行为会如何触发缓存策略

  • 用户输入url,查找disk cache,是否有匹配,有则直接使用,没有则发送请求;
  • 普通刷新(F5):因为窗口并没有关闭,因此memory cache 依然是可用的,会被优先使用(如果匹配的话)。其次才是disk cache
  • 强制刷新(Ctrl+F5):浏览器不使用缓存。因此发送请求头部均带有Cache-Control:no-cache,服务器直接返回200和最新内容;

# 缓存总结

当浏览器需要资源时

  • 1、调用 Service Workerfetch事件响应
  • 2、查看 memory cache
  • 3、查看 disk cache ,这里会细分:
    • 有强缓存且未失效,则使用强制缓存,返回200
    • 有强制缓存已失效,则使用协商缓存,可用返回304 ,不可用返回新数据和200
  • 4、向服务器发送请求,等待响应
  • 5、把响应内容存入 disk cache(如果HTTP头信息配置可存)
  • 6、把 响应内容的引用 存入 memory cache (无视HTTP头信息的配置)
  • 7、把响应内容存入Service WorkerCache Storage(如果Service Worker的脚本调用了cache.put()

# Transfer-Encoding

指定报文主体的传输编码方式

上次更新: 6/24/2021, 7:34:54 PM