非原创
缓存位置
从缓存位置上来看,浏览器缓存分为四种,按照优先级依次查找缓存,如果四个位置都没有命中,那么浏览器就会请求网络获取资源。
优先级由上至下递减
- Service Worker
- Memory Cache
- Disk Cache
- Push Cache
Service Worker
Service Woker 是由开发者编写的额外脚本,运行在浏览器背后的独立线程,它只适用与 https 协议。相比于浏览器其他缓存机制,它完全可以由我们自由控制缓存那些资源、缓存资源的匹配规则、缓存资源的读取规则、缓存持续性。
如果资源没有在 Service Worker 中命中,需要我们手动调用 fetch 函数去获取数据,那么浏览器会按照缓存优先级查找数据。那么不管这个数据是从 Memory Cache 还是网络请求拿到的,浏览器都会显示是从 Service Worker 中获取的。
Memory Cache
Memory Cache: 内存中的缓存,是浏览器自身为加快获取缓存资源速度的优化行为,不受开发者控制、不受 Http 请求头的影响与约束,相当于黑盒的存在。
因为Memory Cache 缓存的位置是在内存中,所以缓存的缓存时间是短期的,一般情况下,当前 浏览器 TAB 关闭后,Memory Chche 就会失效。
什么样的资源可以会被缓存到 Memory Chche 中呢?
- preloader 是在浏览器解析或者执行资源时,请求其他网络资源,使网络请求并行。被 preloader 请求获取的资源大概率会被缓存进 Memory Cache 中。
- preload <link rel="preload" href="" /> 预加载,这些显式指定加载的资源会被放进 Memory Cache 中。
- 网上还有其他观点:文件越小,被加进 Memory Cache 的概率越大。如果当前系统内存使用率较高时,文件会被放到 Disk Cache。
Memory Cache 同时也保证了如果页面上有多个相同的资源请求,比如多个 img 标签请求的 src 相同,那么只会请求一次,避免浪费。
Memory Cache 的匹配规则:
在匹配缓存时,除了匹配完全相同的 URL 外,还会校验比对他们的类型,CORS 中域名规则,因为相同的资源被不同的标签加载是不会获取同一个缓存。
Memory Cache 查找获取资源时会忽略 max-age = 0. no-cache 等 http 头部设置。
如过不希望某个资源被 Memory Cache 缓存,那么需要使用 no-store;
Disk Cache
Disk Cache 也被称为 HTTP Cache(遵守 HTTP 请求头的字段), 持久性存储,存储在文件系统中,允许跨站点、跨会话使用。
缓存规则:
Disk Cache 严格按照 HTTP 请求头信息中的各类字段进行判定资源的缓存。比如判定缓存那些资源、不缓存那些资源、那些资源缓存过期需要重新获取、那些仍然可用。
清除策略
浏览器有自己的算法把 "最老的" 或者 "最有可能过时的" 资源删除。
Push Cache
Push Cache:HTTP/2中内容,缓存时间很短、一次会话结束后便会被释放,只在会话中存在
缓存策略
缓存策略分为:强缓存、协商缓存
简单介绍:
- 强缓存:当浏览器发起请求后,会先访问缓存数据库查看缓存是否存在,如果不存在则需要访问服务器,拿到资源后再加入缓存中。
- 协商缓存:当强制缓存中的资源失效过期后,就需要向服务器进行确认是否失效过期
强缓存
强缓存可直接减少请求数,是提升最大的缓存策略。
可以造成强缓存的 HTTP 请求头的字段 Cache-control 和 Expires
Expires
HTTP/1.0 中的字段,表示缓存到期时间,是一个绝对的时间,用来控制缓存失效的时间格式如下:
Expires: Tue, 14 May 2019 01:48:12 GMT
上述字段的含义表示缓存到 2019年5月14日 失效。在有效期内浏览器不需要向服务器再次请求。
缺陷
1、浏览器通过本地与 Expires 进行比较,那么用户可以通过修改本地时间导致浏览器判断缓存失效,重新请求服务器。
2、过于难写,写法太复杂。多个空格,少个符号都会造成非法属性从而使缓存设置失败。
Cache-control
Cache-control 是 HTTP/1.1 新补充的字段,弥补了 Expires 的缺点,优先级高于 Expries。标识资源可缓存的最大有效时间,在该时间段内,浏览器不会向服务器请求资源。
格式如下:
Cache-control: max-age=2592000
这个时间是一个相对时间,即使浏览器时间发生改变,相对时间也不会发生改变,这样就保持着服务器与浏览器的时间一致性。
简单介绍Cache-control 常用的字段值:
- max-age: 最大的有效时间
- must-revalidate: 如果超过了 max-age 设置的时间,浏览器必须向服务器发送请求,验证资源是否有效。
- no-cache: 字面意思“不缓存”,但并不是不缓存,而是由后续的内容比对决定的。
- no-store:真正意义的“不缓存”,所有的资源都不会走缓存。
- public:所有的内容都可以被缓存(包括客户端、代理服务器。如 CDN)
- private: 所有内容只能被客户端缓存,代理服务等不能缓存。
上述字段值都可以组合使用,但是每个字段都自己的优先级,组合使用时,效果根据优先级决定。
协商缓存
首先解释下,资源虽然通过Cache-Control 或者 Expires 字段设置了资源有效时间,但是过了这个时间并不代表资源已经被废弃不可使用。
当强制缓存失效时,浏览器会向服务器发起请求判断缓存资源是否有效(即是否可以继续使用)
过程如下:
浏览器在缓存中查找资源,发现资源过期。此时会给浏览器返回一个标识,浏览器拿着这个标识去请求服务器,判断资源是否可用。如果服务器根据标识查找并判断资未作改动,仍可继续使用,就会返回一个 304 标识,浏览器继续使用缓存。如果服务器判定资源过期就会返回一份新的资源和缓存规则,浏览器接收后,重新缓存资源。
协商缓存使用的字段
协商缓存使用的是两组字段(组合字段)
Last-Modified 和 If-Modified-Since
1.服务器将 Last-Modified 字段告诉浏览器资源最后一次被修改的时间。
2.浏览器将这个值和资源一起存入缓存中。
3.下一次请求相同资源时,浏览器找出“可能过期的资源”。浏览器在请求服务器时会在请求头上加上 Last-Modified 的值加到 If-Modified-Since 字段中。
4.服务器取出 If-Modified-Since 字段与服务器上文件的 Last-Modified 进行比对,如果相等则表示没有修改,资源仍然可用,返回304;反之,响应状态吗200,并将资源和新的缓存规则返回。
缺陷:
- Last-Modified 是以秒做单位对比的,如果资源是在秒单位内改变,那么服务器仍然会判断资源有效,造成资源的无法及时更新。
- 如果资源是服务器端动态生成的,那么每一次对比,服务器上的资源都是最新的当前时间,所以即使资源没有改变,服务器会判断资源失效,重新发送资源。
Etag 和 If-None-Match
Etag 和 If-None-Match 组合是为了弥补 Last-modified 和 If-Modified-Since 的缺陷出现的。
Etag 保存的是资源的唯一标识,例如 hash。协商的过程和 Last-Modified & If-Modified-Since 一样。
浏览器将 Etag 作为 If-Not-Match 字段的值发送给服务器,服务器获取 If-Not-Match 的值与资源的唯一标识进行比对,如果不同则资源过期重新发送资源和缓存规则,反之返回 304 , 浏览器继续使用缓存资源。
如果两种组合混合使用, Etag & If-Not-Match 组合的优先级高于 Last-Modified & If-Modified-Since
推荐阅读文章
- 一文读懂前端缓存 本文参考
网友评论