前端缓存

一图看懂前端缓存


前端缓存_第1张图片
前端缓存分类图

好了,话不多说,今天主要说说HTTP缓存

(一)使用缓存的优点:

  1. 减少冗余数据的传输
  2. 节省网络费用,缓解网络瓶颈问题
  3. 降低对原始服务器的要求,服务器可以更快响应
  4. 降低距离延迟

(二)浏览器请求资源的过程

第一次请求:
  1. 本地无缓存数据
  2. 向服务器发送请求
  3. 从服务器获取资源,并协商缓存(是否缓存,获取资源的Expires、Cache-Control、Etag、Last-Modified等信息)
  4. 最后呈现页面
再次请求:
  1. 先获取资源的header信息,查看是否命中强缓存(根据cache-control和expires信息判断),若命中直接从缓存中获取资源,包括缓存header信息,本次请求不会与服务器通信
  2. 如果没有命中强缓存,浏览器会发送请求到服务端,请求头中会携带上次请求资源的响应缓存信息(Last-Modified/If-Modified-Since和Etag/If-None-Match),服务器根据header信息判断是否命中协商缓存,若命中,返回新的响应头信息,且不返回资源,浏览器直接从缓存获取,否则,返回更新后的资源信息
强缓存和协商缓存的特点

强缓存:直接使用本地资源,不与服务器通信
协商缓存:与服务器通信,判断命中缓存后再使用本地资源

(三)强缓存相关header字段

与强缓存相关的字段有expires和cache-control,如果cache-control与expires同时存在的话,cache-control的优先级高于expires。
expires:这是http1.0时的规范;它的值为一个绝对时间的GMT格式的时间字符串,如Mon, 10 Jun 2015 21:31:12 GMT,如果发送请求的时间在expires之前,那么本地缓存始终有效,否则就会发送请求到服务器来获取资源
cache-control:max-age=number,这是http1.1时出现的header信息,主要是利用该字段的max-age值来进行判断,它是一个相对值;根据资源上次请求时间和max-age计算出一个资源过期时间,再拿这个过期时间和当前请求时间进行对比,如果请求时间在过期时间之前就命中缓存

其他几个字段:
  1. no-cache:不使用强缓存,与服务器交互判断是否使用协商缓存
  2. no-store:禁止浏览器缓存数据,每次与服务器交互都会返回新的资源信息
  3. public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器
  4. private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存

(四)协商缓存相关header字段

协商缓存需要服务端判断是否命中缓存资源,涉及到以下两组header字段,这两组字段是成对出现的,即第一次请求的响应头带上某个字段(Last-Modified或者Etag),则后续的请求头会带上相应的字段(If-Modified-Since或者If-None-Match),若响应头没有这些字段,则请求头也不会有对应字段

Last-Modified/If-Modified-Since

二者的值都是GMT格式的时间字符串,具体过程:

  1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone的header加上Last-Modified,这个header表示这个资源在服务器上的最后修改时间
  2. 浏览器再次跟服务器请求这个资源时,在request的header上加上If-Modified-Since,这个header的值就是上一次请求时返回的Last-Modified的值
  3. 服务器再次收到资源请求时,根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。当服务器返回304 Not Modified的响应时,response header中不会再添加Last-Modified的header,因为既然资源没有变化,那么Last-Modified也就不会改变,这是服务器返回304时的response header
  4. 浏览器收到304的响应后,就会从缓存中加载资源
  5. 如果协商缓存没有命中,浏览器直接从服务器加载资源时,Last-Modified的Header在重新加载的时候会被更新,下次请求时,If-Modified-Since会启用上次返回的Last-Modified值
Etag/If-None-Match
  1. 这两个值是由服务器生成的每个资源的唯一标识字符串,当资源有变化时,这个值就会改变
  2. 其判断过程与Last-Modified/If-Modified-Since类似,与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化
ETag和Last-Modified的区别
  1. Etag要优于Last-Modified。Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度
  2. 在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值
  3. 在优先级上,服务器校验优先考虑Etag
    利用Etag能够更加准确的控制缓存,因为Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符。
    Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304

(五)缓存位置

缓存的位置大致分为以下三类: Service Worker , Memory Cache ,Disk Cache 。 并且它们的优先级就是按照这个顺序,从前往后寻找,找到即返回;找不到则继续。若最后资源在这些地方都没有找到的话,再去服务器请求资源

service worker

用户自定义缓存哪些资源到硬盘上,什么情况下使用缓存(路由匹配规则),缓存匹配并返回
清空缓存的情况分两种,一是手动调用api,二是容量超过限制,被浏览器清空
这种方式缓存的资源查看方式:开发者工具 -> Application -> Cache Storage
当资源请求被发起的时候,浏览器首先从service worker中查找资源,如果缓存未命中,一般情况会使用fetch()方法继续获取资源,这时浏览器就去memory cache 或disk cache中进行下一次查找缓存的工作
特别注意:经过fetch()方法获取的资源,都会显示 from Service Worker,不管资源实际情况是从memory cache 或disk cache,还是从网络重新请求获取的

memory cache

内存中的缓存,几乎所有的网络请求资源都会被浏览器自动加入到memory cache中,被短期存储,关闭浏览器窗口,memory cache就失效了
从memory cache中获取缓存内容的时候,浏览器会忽视例如max-age=0,no-cache等头部配置
但如果头部配置设置了no-store,那么资源就不会进入memory-cache

disk cache

硬盘上的缓存,持久存储,允许相同资源跨回话跨站点的使用
严格根据HTTP头部字段判定该缓存哪些资源,哪些资源可用,以及哪些资源过期了需要重新请求
当请求命中缓存时,就从硬盘中读取资源。绝大多数的缓存都来自disk cache

如何判断资源是从哪来的

Chrome开发工具 -> network -> 查看size那一列的值
(1)多少多少k:网络请求
(2)form memory cache
(3)from disk cache
(4)from ServiceWorker

浏览器行为

所谓浏览器的行为,指的就是用户在浏览器如何操作时,会触发怎样的缓存策略。主要有 3 种:

  1. 打开网页,地址栏输入地址: 检查是否命中强缓存,若无,再与服务端交互检查协商缓存或者返回数据
  2. 普通刷新 (F5):这种情况下,实际是浏览器将 cache-control 的 max-age 直接设置成了 0,让缓存立即过期,直接走协商缓存路线
  3. 强制刷新 (Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache(为了兼容,还带了 Pragma: no-cache)。服务器直接返回 200 和最新内容。

你可能感兴趣的:(前端缓存)