浏览器缓存机制

179 阅读6分钟

缓存是性能优化的一种方式,可以大大缩短浏览器请求资源的时间。并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷

一、缓存位置

会从缓存位置按顺序查找,当都未命中,然后才会去服务器请求资源。

Service Worker--->Memory Cache--->Disk Cache--->Push Cache

(1)Service Worker:是运行在浏览器背后的独立线程,一般可以用来实现缓存功能

使用 Service Worker的话,传输协议必须为 HTTPS,因为Service Worker涉及到请求的拦截,所以通过HTTPs保证安全。****

Service Worker 实现缓存功能一般分为三个步骤:
  • 首先需要先注册 Service Worker,
  • 监听到 install 事件以后就可以缓存需要的文件,
  • 通过拦截用户访问请求的方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据。

(2) Memory Cache:内存缓存。

主要存贮当前页面中所抓取的资源。例如图片,js文件,css文件等。

会随着进程关闭而释放,也就是一旦我们关闭 Tab 页面,内存中的缓存也就被释放了

注:内存缓存在缓存资源时并不关心cache-control值是什么,会将header中的信息以及URL一并存储,匹配时既会匹配URL又会匹配header中的值。

(3) Disk Cache:磁盘缓存

也就是存储在硬盘中的缓存,这是缓存里面覆盖面最广的,所有资源都可以存储在磁盘中。

(4) Push Cache:推送缓存

当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂

二、浏览器缓存策略:

浏览器缓存策略都是通过设置HTTP Header来实现的。

浏览器缓存过程:

  • 浏览器每次发送请求,都会在浏览器缓存中查找该请求的结果和缓存标识,命中则从缓存读取。
  • 浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中

缓存是否命中:

当命中强缓存,则直接从缓存中读取(不发送请求),未命中强缓存,会去查看是否命中协商缓存(发送请求),命中协商缓存会返回304 not modified ,若未命中协商缓存,则从服务器请求资源返回。

浏览器缓存策略分为两种:强缓存和协商缓存

(1)、强缓存

****强缓存:不会从向服务器发送请求,直接从缓存读取,请求返回状态码为200,并且size显示from disk cache或者from memory cache。

强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。

1、Expires

缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。存在服务器返回的响应头中。

Expires: Wed, 22 Oct 2018 08:41:00 GMT

//表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期,需要再次请求。
**Expires 是 HTTP/1 的产物,受限于本地时间,如果修改了本地时间,可能会造成缓存失效**。

这个方式有一个问题:服务器的时间和浏览器的时间可能并不一致,所以HTTP1.1提出新的字段Cache-Control代替它。

2、Cache-Control

`Cache-Control`是目前(HTTP/1.1)使用最多的缓存规则,主要用于控制网页缓存。会**强制覆盖**掉其他的缓存规则,例如:**Expires或last-modified **

比如当Cache-Control:max-age=300时,则代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存。

Cache-Control 可以在请求头或者响应头中设置,以下是不同的值的不同含义:

参考链接

3、Expires和Cache-Control两者对比

  • Cache-Control优先级高于Expires
  • Expires是http/1的产物(过时),Cache-Control是http/1.1的产物

(2)协商缓存

**协商缓存:会向服务器发送请求,**就是当强缓存失效后,协商缓存会带着缓存标志去发送请求到服务器,由服务器比较是否需要启用此缓存。

  • 协商缓存生效,返回304和Not Modified,从浏览器读取资源
  • 协商返回失效,返回200和新的请求资源与结果

协商缓存可以通过设置两种 HTTP Header 实现:Last-Modified 和 ETag 。

1、Last-Modified:文件的****最后修改时间

浏览器第一次访问资源时,服务器会在资源的同时,在response header中添加 Last-Modified的header,值是这个资源在服务器上的最后修改时间。浏览器接收后缓存文件和header;

Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT

当浏览器再次请求,会在请求头中携带If-Modified-Since,这个字段的值就是服务器传来的最后修改时间Last-Modified,服务器再次收到请求后,会将If-Modified-Since与服务器中该资源的最后修改时间相比:

  • 大于,则表示资源未被修改,则返回304 not modified
  • 小于则表示资源已被修改,会返回200和将更新后的资源返回,客户端会更新资源的缓存时间,以及资源。

2、ETag:文件的唯一标识

Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成

浏览器在第一次访问资源时,会在返回的响应头中添加Etag,以及返回相应的资源,浏览器接受后缓存文件及header。

浏览器**再次请求,**会在请求头中将上一次的Etag值赋值给此次请求header中的If-None-Match,服务器收到请求后比对该资源的EtagIf-None-Match是否相同:

  • 相同,则返回304 not modified,
  • 不同,则标识资源被更改,返回200及新的资源与响应头中新的Etag,更新缓存中的资源以及header。

3、两者之间对比

  • 精度上:Etag会比****Last-Modified更精确,前者比较文件内容,后者比较文件修改时间(当编辑某个文件,但是并未修改内容,也会改变最后修改时间)
  • **性能上:Etag要逊于Last-Modified,**毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值
  • 优先级:Etag高于Last-Modified

三、实际场景应用

1、对于经常改变的资源:

Cache-Control: no-cache

2、对于常时间不改变的资源:

Cache-Control: max-age=31536000  (一年)