浏览器缓存与Lru-Cache(浏览器缓存与cookie的区别)
思考
浏览器缓存是什么样的行为?
Lru-Cache是什么?和浏览器缓存有什么关系?
浏览器缓存
定义:
浏览器将网络资源存储在本地的一种行为
存储位置:
存储类型:非脚本类型,比如css
不会被清除-退出进程时
存储类型:一般的脚本、字体、图片等
何时被清除:退出进程时(关闭tab页面)
Service Worker
:离线缓存,JS
运行在主线程外(这也是无法直接访问DOM的原因),达到离线缓存、网络代理等目的memory cache
:内存,默认存储位置disk cache
:磁盘prefetch cache
:预取,被标记为prefetch
的资源,会在浏览器空闲时间被加载push cache
:推送缓存,只在session
中存在缓存的过程:
字段相关:
设置:
再次请求时,携带之前的
Last-Modified
;服务器对比
Last-Modified-Since
与Last-Modified
,对应返回;Last-Modified
:响应时,返回该资源最后被修改的时间 (缓存标识)Etag
:响应时,返回当前资源的唯一标识 (缓存标识)If-Modified-Since
:If-None-Match
:再次请求时,携带之前的Etag
,服务器识别该字段,对比Etag
,一致返回304
;使用缓存资源;否则返回200
和新资源资源没更改:返回
304
,读取本地资源;资源更改:返回
200
和新资源携带本地资源的
Last-Modified
,服务器对比:携带本地资源的
Etag
标识,服务器对比:缓存字段相关:
设置:
注意点:
cache-control
时间段需与服务器资源更新错开public
: 都可缓存private
:仅客户端可缓存no-cache
:客户端缓存; 服务端是否缓存需要验证no-store
:不使用缓存max-age
:缓存保质期expires
:缓存到期时间---通过本地时间判断cache-control
:使用max-age相对时间pragma
:禁用缓存根据请求头参数,符合强缓存则返回
200
,从本地缓存读数据;否则请求头携带响应参数,判断是协商缓存则返回
304
;否则返回新资源首次访问:根据响应头中字段
expires
、pragma
或者cache-control
,判断是否缓存以及缓存位置第二次访问:
强缓存:访问URL地址时,直接从缓存中读取资源,返回
200
状态码协商缓存:浏览器携带缓存标识发起请求,由服务器决定是否使用缓存;一般是在强缓存失效后
缓存过程决定于:通过
Cache-Control
验证强缓存是否可用缓存方案选择
contenthash
:由文件内容生成的hash
,不同内容得到不同hash
推荐使用理由:生产环境中打包,第一次访问后会缓存;第二次打包发布后,刷新还是之前的资源(名字相同);
output
文件名加上哈希值HTML类型:协商缓存
CSS、JS、图片:强缓存
文件名带上
hash
值---hash
值修改则第一时间请求最新资源最佳:减少请求、更多使用本地资源---尽可能命中强缓存、同时更新版本时让客户端缓存失效
在webpack中打包的应用:哈希值
浏览器缓存淘汰策略方式之一:LRU
缓存淘汰策略:一种防止缓存空间占满的方式,对数据进行保留、移除
LRU
(Least Recently Used):最近最少使用缓存淘汰策略,根据数据历史访问记录进行淘汰数据。获取排位第一的键值:
map.keys().next()
---淘汰最近没被访问key原理:2.5版本后的
vue
,keep-alive
新增max
属性:代表最多可缓存组件实例数;新增缓存实例会优先淘汰最近没被访问的实例实现:
判断
cache
是否已缓存,是则直接获取,移除keys
中对应key
值放入keys
数组最后一位否则进行缓存实例
当
keys
长度大于max
时,移除keys[0]
缓存cache
对象:保存缓存组件的实例和key
值keys
数组:保存缓存组件的key
渲染一个缓存实例时:
关键思想:数据最近被访问过,则代表将来被访问几率更高---优先淘汰最近没被访问的数据
在vue组件中的应用:
keep-alive
的缓存组件(切换组件时不卸载)举例:实现
LRU
缓存机制
class LRUCache { constructor(capacity){ this.capacity = capacity this.map = new Map() } get(key){ let val = this.map.get(key) //获取key对应val if(typeof val === 'undefined') return -1 //被访问,修改key的位置 this.map.delete(key) this.map.set(key, val) return val } put(key, val){ if(this.map.has(key)){ this.map.delete(key) } this.map.set(key, val) //超出限制,优先淘汰 let keys = this.map.keys() if(this.map.size > this.capacity){ this.map.delete(keys.next().value) } } }
作者:用户8249761345499
链接:https://juejin.cn/post/7034024330728046606