以下文章来源于QQ音乐前端团队 ,作者kevinylzhao
QQ音乐WEB前端团队
浏览器缓存策略对于前端开发同学来说不陌生,大家都有一定的了解,但如果没有系统的归纳总结,可能三言两语很难说明白,甚至说错,尤其在面试过程中感触颇深,很多候选人对这类基础知识竟然都是一知半解,说出几个概念就没了,所以重新归纳总结一下,温故而知新
浏览器缓存一般分为两类:强缓存(也称本地缓存)和协商缓存(也称弱缓存)
浏览器发送请求前,会先去缓存里查看是否命中强缓存,如果命中,则直接从缓存中读取资源,不会发送请求到服务器。否则,进入下一步。
当强缓存没有命中时,浏览器一定会向服务器发起请求。服务器会根据Request Header中的一些字段来判断是否命中协商缓存。如果命中,服务器会返回304响应,但是不会携带任何响应实体,只是告诉浏览器可以直接从浏览器缓存中获取这个资源。如果本地缓存和协商缓存都没有命中,则从直接从服务器加载资源。
按照本地缓存阶段和协商缓存阶段分类:
在HTTP请求和响应的消息报头中,常见的与缓存有关的消息报头有:
上图中只是常用的消息报头,下面来看下不同字段之间的关系和区别:
max-age:
功能和Expires类似,但是后面跟一个以“秒”为单位的相对时间,来供浏览器计算过期时间。
no-cache:
提供了过期验证机制。
no-store:
表示当前请求资源禁用缓存。
public:
表示缓存的版本可以被代理服务器或者其他中间服务器识别。
private:
表示只有用户自己的浏览器能够进行缓存,公共的代理服务器不允许缓存。
Cache-Control:
HTTP1.1提出的特性,为了弥补 Expires 缺陷加入的,提供了更精确细致的缓存功能。
详细了解详细看几个常见的指令:
浏览器可以在内存、硬盘中开辟一个空间用于保存请求资源副本。我们经常调试时在DevTools Network里看到Memory Cache(內存缓存)和Disk Cache(硬盘缓存),指的就是缓存所在的位置。请求一个资源时,会按照优先级(Service Worker -> Memory Cache -> Disk Cache -> Push Cache)依次查找缓存,如果命中则使用缓存,否则发起请求。这里先介绍 Memory Cache 和 Disk Cache。
表示不访问服务器,直接从内存中读取缓存。因为缓存的资源保存在内存中,所以读取速度较快,但是关闭进程后,缓存资源也会随之销毁,一般来说,系统不会给内存分配较大的容量,因此内存缓存一般用于存储较小文件。同时内存缓存在有时效性要求的场景下也很有用(比如浏览器的隐私模式)。
表示不访问服务器,直接从硬盘中读取缓存。与内存相比,硬盘的读取速度相对较慢,但硬盘缓存持续的时间更长,关闭进程之后,缓存的资源仍然存在。由于硬盘的容量较大,因此一般用于存储大文件。
下图可清晰看出差别:
在preload或prefetch的资源加载时,两者也是均存储在http cache,当资源加载完成后,如果资源是可以被缓存的,那么其被存储在http cache中等待后续使用;如果资源不可被缓存,那么其在被使用前均存储在memory cache;
以腾讯CDN为例 X-Cache-Lookup:Hit From MemCache 表示命中CDN节点的内存 X-Cache-Lookup:Hit From Disktank 表示命中CDN节点的磁盘 X-Cache-Lookup:Hit From Upstream 表示没有命中CDN
从上图能感受到整个流程,比如常见两种刷新场景:
IndexedDB 就是浏览器提供的本地数据库,能够在客户端存储可观数量的结构化数据,并且在这些数据上使用索引进行高性能检索的API。异步 API 方法调用完后会立即返回,而不会阻塞调用线程。要异步访问数据库,要调用 window 对象 indexedDB 属性的 open() 方法。该方法返回一个 IDBRequest 对象 (IDBOpenDBRequest);异步操作通过在 IDBRequest 对象上触发事件来和调用程序进行通信。常用异步API如下:
SW从2014年提出的草案到现在已经发展很成熟了,基于SW做离线缓存,让用户能够进行离线体验,消息推送体验,离线缓存能力涉及到Cache和CacheStorage的概念,篇幅有限,不展开了
localStorage 属性允许你访问一个 Document 源(origin)的对象 Storage 用于存储当前源的数据,除非用户人为清除(调用 localStorage api 或则清除浏览器数据), 否则存储在 localStorage 的数据将被长期保留
sessionStorage 属性允许你访问一个 session Storage 对象,用于存储当前会话的数据,存储在 sessionStorage 里面的数据在页面会话结束时会被清除。页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍会保持原来的页面会话。
通过了解浏览器各种缓存机制和存储能力特点,结合业务制定合适的缓存策略,善用缓存是基本功,可以用于时常审查负责的业务,可能就会发现个别业务并没有运用到位,共勉。
https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
https://www.digitalocean.com/community/tutorials/web-caching-basics-terminology-http-headers-and-caching-strategies
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching_FAQ
https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API
https://juejin.im/post/5a673af06fb9a01c927ed880
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn