
图片
第二个缓存位置
从缓存位置开始,有四种类型,每种类型都有一个优先级. 依次搜索缓存但未命中任何缓存时,将请求网络.
1.Service Worker
Service Worker是运行在浏览器后面的独立线程,通常可用于实现缓存功能. 如果使用Service Worker,则传输协议必须为HTTPS. 由于服务工作者涉及请求拦截,因此必须使用HTTPS协议来确保安全性. Service Worker的缓存与浏览器中其他内置的缓存机制不同. 它使我们能够自由控制要缓存的文件,如何匹配缓存,如何读取缓存以及连续的缓存.
Service Worker实现缓存功能,通常分为三个步骤: 首先,需要注册Service Worker,然后在侦听安装事件之后,可以缓存所需的文件,然后可以通过拦截请求来进行查询. 用户下次访问时是否存在缓存,如果存在缓存,则可以直接读取缓存文件,否则可以请求数据.
当Service Worker没有访问缓存时,我们需要调用fetch函数来获取数据. 换句话说,如果我们未在Service Worker中命中缓存,则将根据缓存查找优先级来查找数据. 但是,无论我们是从内存缓存还是从网络请求中获取数据,浏览器都将显示我们是从Service Worker中获取内容的.
2. 内存缓存
内存缓存是内存中的缓存,主要包含当前页面中已获取的资源,例如已下载到该页面上的样式,脚本,图片等. 读取内存中的数据肯定比磁盘快. 尽管内存高速缓存的读取效率很高,但高速缓存的持续时间非常短,并且会在释放进程时释放. 关闭标签页后,将释放内存中的缓存.
因此,由于内存缓存非常高效,我们可以将所有数据存储在内存中吗?
这是不可能的. 计算机中的内存必须比硬盘的容量小得多. 操作系统需要仔细计划内存的使用,因此我们可以使用的内存不能太多.
访问页面后,再次刷新页面,我们可以发现很多数据来自内存缓存
图片
内存高速缓存中的重要高速缓存资源是通过与预加载器相关的指令下载的资源(例如). 众所周知,预加载器的相关指令已经是页面优化的常用方法之一. 它可以解析js / css文件,同时从Internet请求下一个资源.
需要注意的是,当内存缓存正在缓存资源时,它并不关心返回资源的HTTP缓存头Cache-Control的值是什么. 同时,资源的匹配不仅要匹配URL,还要检查ContentType,CORS和其他功能.
3. 磁盘缓存

磁盘缓存是存储在硬盘中的缓存. 读取速度较慢,但是所有内容都可以存储在磁盘上. 与内存缓存相比,它的容量和存储及时性更好.
在所有浏览器缓存中,磁盘缓存基本上具有最大的覆盖范围. 它将根据HTTP Herder中的字段确定哪些资源需要缓存,哪些资源可以直接使用而无需请求,哪些资源已过期并且需要再次请求. 甚至在跨站点的情况下,一旦相同地址的资源被硬盘缓存,它们将不会再次请求数据. 大部分缓存来自磁盘缓存. 我们将在下面详细介绍HTTP协议标头中的缓存字段.
浏览器将哪些文件放入内存?扔进硬盘的是什么?
关于这一点,Internet上存在不同的观点,但是以下观点更可靠:
4. 推送缓存
推送缓存是HTTP / 2中的内容. 当上述三个缓存均未命中时将使用它. 它仅存在于会话中,在会话结束后被释放,并且缓存时间也非常短,在Chrome浏览器中只有大约5分钟,并且它没有严格实现HTTP标头中的缓存指令.
推缓存在中国几乎没有可用的信息,这也是因为HTTP / 2在中国不够流行. 建议阅读Jake Archibald的HTTP / 2推送比我认为的要难,并且文章中有一些结论:
如果以上四个缓存均未命中,那么您只能发起请求以获取资源.
因此,出于性能方面的考虑,大多数接口都应选择良好的缓存策略. 通常,浏览器缓存策略分为两种: 强缓存和协商缓存,并且缓存策略是通过设置HTTP标头实现的.
三,缓存过程分析
浏览器与服务器通信的方式是响应模式,即: 浏览器启动HTTP请求-服务器响应该请求,然后浏览器如何确定是否应缓存资源以及如何缓存资源?浏览器首次向服务器发起请求并获得请求结果后,它将请求结果和缓存标识符存储在浏览器缓存中. 浏览器对缓存的处理取决于首次请求资源时返回的响应标头. 具体过程如下:
首次发起HTTP请求
从上面的图片中,我们可以知道:
以上两个结论是浏览器缓存机制的关键. 它确保存储和读取每个请求的缓存. 只要我们了解使用浏览器缓存的规则,所有问题都将得到解决. 本文还将围绕这一点进行详细分析. 为了使每个人都更容易理解,在此,根据是否需要向服务器重新发起HTTP请求,将缓存过程分为两部分,即强缓存和协商缓存.
四个强大的缓存
强大的缓存: 不会将请求发送到服务器,直接从缓存中读取资源,您可以看到该请求在chrome控制台的“网络”选项中返回状态码200,并且“大小”从磁盘显示高速缓存或从内存高速缓存. 可以通过设置两个HTTP标头来实现强大的缓存: Expires和Cache-Control.
1. 到期

缓存过期时间,用于指定资源过期的时间,它是服务器端的特定时间点. 换句话说,Expires = max-age + request time,需要与Last-modified一起使用. 过期是Web服务器响应消息的标头字段. 当响应http请求时,它告诉浏览器,浏览器可以在到期之前直接从浏览器缓存中获取数据,而无需再次请求.
Expires是HTTP / 1的产品,并且限于本地时间. 如果修改了本地时间,则缓存可能无效. 过期: 2018年10月22日星期三08:41:00 GMT意味着资源将在格林尼治标准时间2018年10月22日星期三08:41:00之后过期,需要再次请求.
2.Cache-Control
在HTTP / 1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存. 例如,当Cache-Control: max-age = 300时,这意味着如果在正确的请求返回时间(也将由浏览器记录)的5分钟内再次加载资源,则强缓存将为命中.
可以在请求标头或响应标头中设置缓存控制,并且可以组合使用多个命令:
图片
public: 将缓存所有内容(客户端和代理服务器均可缓存). 具体来说,响应可以由任何中间节点(例如浏览器)缓存
private: 只有客户端可以缓存所有内容,这是Cache-Control的默认值. 具体来说,这意味着中间节点不允许对浏览器进行缓存
no-cache: 客户端缓存内容. 是否使用缓存,您需要协商缓存以验证该决定. 这意味着Cache-Control的缓存控制方法不用于预验证,而Etag或Last-Modified字段用于控制缓存. 应该注意的是,no-cache这个名字有点误导. 设置无缓存后,并不意味着浏览器不再缓存数据,而是在浏览器使用缓存的数据时,需要确认数据是否仍与服务器一致.
不存储: 将不缓存所有内容,即不使用强制性缓存或协商性缓存
max-age: max-age = xxx(xxx为数字)表示缓存的内容将在xxx秒后过期
s-maxage(单位: s): 与max-age相同,仅在代理服务器(例如CDN缓存)中有效. 例如,当s-maxage = 60时,在这60秒钟内,即使CDN的内容被更新,浏览器也不会发出请求. max-age用于常规缓存,而s-maxage用于代理缓存. s-maxage的优先级高于max-age. 如果存在s-maxage,则max-age和Expires标头将被覆盖.
max-stale: 可以忍受的最大到期时间. max-stale指令指示客户端愿意接收已过期的响应. 如果指定了max-stale的值,则最大容忍时间为相应的秒数. 如果未指定,则浏览器愿意接收任何年龄响应(年龄表示源站点生成或确认响应的时间与当前时间之间的差).
最小新鲜度: 可以忍受的最小新鲜度. min-fresh表示客户端不愿意接受其新鲜度不超过当前年龄加上min-fresh设置的时间的响应.
缓存控制
从图中可以看出,我们可以一起使用多个指令来实现多个目标. 例如,我们希望可以缓存资源,并且可以缓存客户端和代理服务器,并且可以设置缓存过期时间.

3. Expires和Cache-Control之间的比较
实际上,两者之间没有太大区别. 区别在于Expires是http1.0的产品,而Cache-Control是http1.1的产品. 如果两者同时存在,则Cache-Control的优先级高于Expires;在某些情况下,Expires在不支持HTTP1.1的环境中将很有用. 因此Expires实际上是一个过时的产品,它在现阶段的存在只是一种兼容的方式.
强缓存会根据缓存是超过一定时间还是一段时间来判断缓存,而不关心服务器端文件是否已更新,这可能导致加载的文件不是最新的服务器端的内容,那么我们怎么知道服务器端的内容是否已更新?此时,我们需要协商一种缓存策略.
5. 协商缓存
缓存协商是一个过程,在该过程中,浏览器携带缓存标识符,以在迫使缓存过期后向服务器发起请求,然后服务器根据缓存标识符来决定是否使用缓存. 主要有两种情况:
协商缓存无效
可以通过设置两个HTTP标头来实现协商缓存: Last-Modified和ETag.
1.Last-Modified-If-Modified-Since
当浏览器第一次访问资源时,当服务器返回资源时,它将Last-Modified头添加到响应头. 该值是服务器上资源的最后修改时间. 浏览器在收到文件和标头后将其缓存. ;
Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT
下次浏览器请求此资源时,浏览器检测到Last-Modified标头,因此添加了If-Modified-Since标头,该值是Last-Modified中的值;服务器再次接收到该资源请求,它将根据If-Modified-Since中的值与服务器中资源的上次修改时间之间的比较,如果没有更改,则返回304并且为空的响应主体,直接从缓存读取. 如果服务器中If-Modified-Since的时间小于此时间,则资源的最后修改时间表示文件已更新,因此返回新的资源文件和200.
图片
但是Last-Modified有一些缺点:
由于使用文件修改时间来确定缓存是否不足,是否可以根据文件内容是否被修改直接确定缓存策略?因此ETag和If-None-Match出现在HTTP / 1.1中
2.ETag和If-None-Match
Etag是唯一标识符(由服务器生成),当服务器响应请求时,服务器将其返回到当前资源文件. 只要资源更改,Etag就会重新生成. 下次浏览器加载资源并将请求发送到服务器时,它将把上次返回的Etag值放在请求标头中的If-None-Match中. 服务器仅需要将来自客户端的If-None-Match与自己的服务器进行比较. 如果资源的ETag相同,则可以判断资源是否相对于客户端已被修改. 如果服务器发现ETag不匹配,则以常规GET 200返回数据包的形式直接将新资源(包括新的ETag)发送到客户端. 如果ETag一致,则直接返回304,以通知客户端直接使用本地缓存.

ETag和If-None匹配
3. 两者之间的比较:
Last-Modified的时间单位为秒. 如果文件在1秒内被多次更改,则它们的Last-Modified实际上不会反映该修改,但是Etag每次都会更改以确保准确性;如果是负载平衡服务器,则每个服务器生成的Last-Modified也可能不一致.
六个. 缓存机制
强制缓存优先于协商缓存. 如果强制性缓存(Expires和Cache-Control)生效,则将直接使用该缓存;如果该缓存不生效,则协商缓存(Last-Modified / If-Modified-Since和Etag / If-None)-Match). ,协商缓存由服务器确定是否使用该缓存,如果协商缓存无效,则表示请求的缓存无效,返回200,重新返回资源和缓存标识,然后将其存储在浏览器中缓存如果生效,则返回304,继续使用缓存. 具体流程图如下:
缓存机制
看到这一点,我不知道您是否有这样的问题: 如果未设置缓存策略,浏览器会做什么?
在这种情况下,浏览器将使用启发式算法,通常将响应标头中的Date减去Last-Modified值的10%作为缓存时间.
七. 实际方案应用的缓存策略1.频繁更改资源
缓存控制: 无缓存
对于频繁更改的资源,您首先需要使用Cache-Control: no-cache使浏览器每次都请求服务器,然后使用ETag或Last-Modified验证资源是否有效. 尽管这种方法无法保存请求数,但可以大大减少响应数据的大小.
2. 不常更改的资源
缓存控制: max-age = 31536000
通常,在处理此类资源时,为其Cache-Control配置一个较大的max-age = 31536000(一年),以便浏览器在以后请求相同URL时会进入强制缓存. 为了解决更新问题,有必要在文件名(或路径)中添加哈希和版本号等动态字符,然后进行更改,以达到更改参考URL的目的,并使以前的强制无效. 缓存(实际上,它不是立即无效的,只是不再使用).
库(例如jquery-3.3.1.min.js,lodash.min.js等)都采用这种模式.
8. 用户行为对浏览器缓存的影响
用户行为对浏览器缓存的影响是指当用户操作浏览器时触发哪种缓存策略. 主要有三种类型:
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shumachanpin/article-299319-1.html
说下感受吧