浏览器缓存机制

在这里插入图片描述
缓存可以说是性能优化中简单有效的方式之一,它可以显著减少网络传输所带来的损耗.

对于一个数据请求来说,可以分为发送网络请求,后端处理,浏览器响应三个步骤。浏览器缓存可以帮助我们在第一和第三步骤中优化性能。比如说直接使用缓存而不发送请求,或者是发送了请求但后端存储的数据和前端一直,那么就没有必要在将数据会传过来,这样就减少了数据响应。

下面从三部分来讨论浏览器缓存机制

  • 缓存位置
  • 缓存策略
  • 实际场景应用缓存策略
缓存位置

从缓存位置上来说分为四种,并且各自有各自的优先级,当依次查找缓存且都没有命中的时候,才会去请求网络

  1. Service Worker
  2. Memory Cache
  3. Disk Cache
  4. Push Cache
  5. 网络请求
Service Worker

这篇文章不错
Service Worker是运行在浏览器背后的独立线程,一般可以用来实现缓存功能,使用Service Worker的话,传输协议必须为HTTPS。因为Service Worker中涉及到请求拦截,所以必须使用HTTPS协议保障安全。

Service Worker实现缓存功能一般分为三个步骤:首先需要先注册Service Worker,然后监听到install(安装)事件以后就可以缓存需要的文件,当下次用户访问的时候就可以通过拦截请求的方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据

Service Worker的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件,如何匹配缓存,如何读取缓存,并且缓存是持续性的。

当 Service Worker 没有命中缓存的时候,我们需要去调用 fetch 函数获取数据。也就是说,如果我们没有在 Service Worker 命中缓存的话,会根据缓存查找优先级去查找数据。但是不管我们是从 Memory Cache 中还是从网络请求中获取的数据,浏览器都会显示我们是从 Service Worker 中获取的内容。

Memory Cache 内存缓存

MemoryCache顾名思义,就是将资源缓存到内存中,等待下次访问时不需要重新下载资源,而直接从内存中获取。Webkit早已支持memoryCache。
目前Webkit资源分成两类,一类是主资源,比如HTML页面,或者下载项,一类是派生资源,比如HTML页面中内嵌的图片或者脚本链接,分别对应代码中两个类:MainResourceLoader和SubresourceLoader。虽然Webkit支持memoryCache,但是也只是针对派生资源,它对应的类为CachedResource,用于保存原始数据(比如CSS,JS等),以及解码过的图片数据。

读取内存中的数据肯定要比磁盘块,但是内存缓存虽然读取高效,可是缓存持续性很短,会随着进程的释放而释放。一旦我们关闭Tab页面,内存中缓存也就被释放了。

Disk Cache 磁盘缓存

Disk Cache 也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上。

在所有浏览器缓存中,Disk Cache 覆盖面基本是最大的。它会根据 HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。并且即使在跨站点的情况下,相同地址的资源一旦被硬盘缓存下来,就不会再次去请求数据。

Push Cache

Push Cache是HTTP/2中的内容,当上面三种缓存都没有命中的时候,它才会被使用,并且缓存时间也很短暂,只在会话(Session)中存在,一旦会话结束就被释放

所有的资源都能被推送,但是 Edge 和 Safari 浏览器兼容性不怎么好
可以推送 no-cache 和 no-store 的资源
一旦连接被关闭,Push Cache 就被释放
多个页面可以使用相同的 HTTP/2 连接,也就是说能使用同样的缓存
Push Cache 中的缓存只能被使用一次
浏览器可以拒绝接受已经存在的资源推送
你可以给其他域名推送资源

网络请求

缓存没有命中只能发送网络请求

缓存策略

通常浏览器缓存策略分为两种:强缓存和协商缓存,并且缓存策略上都是通过设置HTTP Header来实现的。

强缓存

用户发送的请求,直接从客户端缓存中获取,不发送请求到服务器,不与服务器发生交互行为。
强缓存可以通过设置两种HTTP Header实现:Expires和Cache-Control。强缓存表在缓存期间不需要请求,state code为200

Expires

Expires: Wed, 22 Oct 2018 08:41:00 GMT

Http1.0 中的标准,表明过期时间,注意此处的时间都是指的是服务器的时间。
可以看到过期时间被设定为了:Wed, 22 Oct 2018 08:41:00 GMT(不统一)
存在的问题:服务器时间与客户端时间的不一致,就会导致缓存跟期待效果出现偏差。意思就是如果修改了本地时间,可能会造成缓存失效

Cache-control

Cache-control: max-age=30

Cache-Control 出现于 HTTP/1.1,优先级高于 Expires 。该属性值表示资源会在 30 秒后过期,需要再次请求。
在这里插入图片描述

在这里插入图片描述

协商缓存

用户发送的请求,发送到服务器后,由服务器判定是否从缓存中获取资源。

如何缓存过期了,就需要发起请求验证资源是否有更新,协商缓存可以通过设置两种HTTP Header实现:Last-Modified和ETage。
浏览器将在request header 中加入If-Modified-Since(对应于Last-modified), 和If-None-Match(对应于Etag)。
Last-modified: 表明请求的资源上次的修改时间。
If-Modified-Since:客户端保留的资源上次的修改时间。
Etag:资源的内容标识。(不唯一,通常为文件的md5或者一段hash值,只要保证写入和验证时的方法一致即可)
If-None-Match: 客户端保留的资源内容标识。

⚠️:
1) 分布式系统尽量关闭Etag,因为每台机器生成的Etag都不一样。
2)分布式系统里多台机器间文件的Last-Modified必须一致,以免负载均衡不同导致对比失败。

通常情况下,如果同时发送 If-None-Match 、If-Modified-Since字段,服务器只要比较etag 的内容即可,当然具体处理方式,看服务器的约定规则。

两者共同点:客户端获得的数据最后都是从客户端缓存中获得。

两者的区别:从名字就可以看出,强缓存不与服务器交互,而协商缓存则需要与服务器交互。

实际场景应用缓存策略
频繁变动的资源

对于频繁变动的资源,首先需要使用 Cache-Control: no-cache 使浏览器每次都请求服务器,然后配合 ETag 或者 Last-Modified 来验证资源是否有效。这样的做法虽然不能节省请求数量,但是能显著减少响应数据大小。

代码文件

这里特指除了 HTML 外的代码文件,因为 HTML 文件一般不缓存或者缓存时间很短。

一般来说,现在都会使用工具来打包代码,那么我们就可以对文件名进行哈希处理,只有当代码修改后才会生成新的文件名。基于此,我们就可以给代码文件设置缓存有效期一年 Cache-Control: max-age=31536000,这样只有当 HTML 文件中引入的文件名发生了改变才会去下载最新的代码文件,否则就一直使用缓存。

参考文件(大部分都是复制的啊)

前端面试之道

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值