缓存属于优化的一部分,好的缓存机制可以减少相应的数据请求,从而降低服务器的压力。另一方面,也会减少部分的请求时间,提高了响应速度和用户体验。
一、浏览器缓存的方式
数据如果存储在后端,那么一般一个请求要经过: 请求发起、后台处理、浏览器响应。
1、 通过减少请求
如果知道数据没有发生变化,那么就不必再请求一次,直接缓存在本地。
2、后端不再返回数据
如果后端收到请求,发现数据没有发生变化,就不再重复返回同样的数据。这也是一种浏览器缓存的方式。
二、缓存位置
- Service Worker
- Memory Cache
- Disk Cache
- Push Cache
SW是运行在浏览器背后的独立线程,一般可用于缓存,使用它必须是https的传输协议。因为SW涉及请求拦截,要用https协议保障安全。他跟其他缓存机制不同,可以让我们自由控制缓存哪些文件,如何匹配缓存、读取缓存,且使缓存持续。
步骤是: 注册SW,监听install事件。当用户再次访问,可以通过拦截判断是否缓存,有的话就直接读取缓存文件,如果没有命中,去调用fetch函数获取数据。
这就是,如果没在SW命中,根据查找优先级查找数据。不过即便我们MC中或请求来的数据,都会显示是SW获取的。
MC-内存中的缓存。主要指当前页面已抓到的资源,如CSS、Script、picture等。读内存比磁盘快,但持续性短,随着进程释放而释放,我们关闭Tab页就会被释放。
而且内存小于硬盘,不要滥用。MC重要的缓存资源是preloader相关指令,如
<link rel="prefetch">
下载的资源,这些相关指令时优化的常见手段,一边解析js、css文件,一边网络请求下一个资源。
内存缓存不关心返回的资源http缓存头Cache-Control是什么,资源匹配页不仅仅是对URL做匹配,还可能会对content-type,cors等其他特征做校验
DC-硬盘中缓存,speed慢一点,但时效性、容量比MC强。DC覆盖面最大。根据http header字段判断哪些需要缓存,哪些已经过期。即时跨站点,相同地址资源一旦被DC缓存,就再也不会请求。
大文件,在硬盘比较好
系统内存如果使用率高先存入硬盘
PC-推送缓存,HTTP/2的内容,上三种都没命中才会使用,只在session会话存在,缓存时间短暂,chrome5分钟左右。
上面那些都没命中,可以通过在发起请求时设置缓存策略来优化。
三、浏览器缓存的过程
第一次浏览器发起请求,服务器并没有返回缓存策略请求头,第二次请求,返回加上缓存策略的请求头,浏览器将策略标识存下来,下一次请求就用到了。每次发起请求都会在浏览器缓存中找,每次拿到结果和缓存标识都会存下来。根据是否需要重新向服务器发出请求分为强缓存和协商缓存。
1、强缓存
强缓存是从浏览器里拿到数据,不需要跟服务器进行通信。
1.1 强缓存相关header字段
cache-control-级别最高,值是一个时间段,需要记住请求时间是不是在这个时间段内,服务端和客户端时间必须一致。因为这是个时间段,可设置一些默认值:
- no-cache: 从不使用本地缓存
- public: 任何时间都可以缓存
- private: 只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存
- no-store:禁止浏览器缓存数据,也禁止保存至临时文件中,每次都要重新请求,此值优先级最高。
expires-未来时间,表示请求的有效期,没过期之前就用这个请求。
1.2 强缓存刷新后的处理
F5刷新后失效,Ctrl+F5刷新后无效
1.3 强缓存如何重新加载缓存过的资源
更新页面中引用的资源路径,让浏览器主动放弃缓存,加载新的资源。
2 协商缓存
请求至服务器,让服务器来判断是否直接使用本地缓存。
2.1 相关header字段
Last-Modified/If-Modified-Since: 都是时间格式字符串。
浏览器先发一次请求,服务器在返回的response的header里加上Last-Modified表示最后修改的时间,再请求资源,在request的header里加上If-Modified-Since,值就是上次返回的Last-Modified的值。服务器根据请求的header值判断资源是否有变化,没变化返回304 ,304从缓存加载资源。
Etag/If-None-Match 标识字符串
与上面不同的是,返回304时,ETage还是会重新生成返回至浏览器。
2.2 协商缓存的特点
有些文件可能周期性更改,但内容没修改时,用Etag就不用重新拉取,1秒内修改的文件也会被检测到。
2.3 协商缓存都是两个属性同时出现
协商是浏览器判断资源是否可用,所以需要两个标识: 第一个是第一次请求的响应头带上某个字段,第二个是后续请求的请求头带上的字段。
2.4刷新
F5刷新后依然有效, Ctrl+ F5刷新后无效