谈谈浏览器的缓存机制

谈谈浏览器的缓存机制

概述

缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。在开发过程中随处可见,小到Javasript作用域内的变量存储,大到使用CDN使静态资源的分布存储到缓存服务器上等。缓存的简单解释就是将我们的计算结果储存,当下一次计算时,可以将保存的结果值快速返回。(类似于CPU寄存器)

谈谈浏览器的缓存机制_第1张图片

什么是浏览器缓存

浏览器缓存(Browser Caching)是为了节约网络的资源加速浏览,浏览器在用户磁盘上对静态资源进行存储,当再次请求该页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览。而浏览器缓存,本质上就是HTTP的缓存。

HTTP缓存就是将第一次请求的结果存储起来,当下一次请求发起时,可以快速匹配对应的缓存文件。这样就节省了请求的时间,达到了提高网页效率的目的。

来看看缓存简单应用的流程图:

谈谈浏览器的缓存机制_第2张图片

图中,假设先不考虑缓存过期的问题,对同一个请求,发起了两次:

  • 第一次是未匹配到缓存资源,因此又向服务端发起了一次真实的请求,返回了对应的响应结果以及携带了缓存相关的标识(后面会讲)。
  • 第二次从缓存中匹配到资源结果,因此,就省去了想服务端发送的请求,直接从缓存中返回对应的结果。

对比两次请求的时间,可以看到缓存带来的优点:

  • 加快页面加载速度 从缓存中的请求时长少于服务器发起的请求时长
  • 减少网络延迟和带宽消耗 读取本地缓存
  • 降低服务端压力

问题

看到这里,我们就可能会产生一些疑问:

  1. 浏览器缓存都有哪些类型
  2. 浏览器的缓存机制
  3. 服务端返回的响应中,有带有哪些缓存的规则
  4. 浏览器发起的请求体中,有会带上哪些缓存的标识
  5. 如何判断缓存是否有效

下面我们就来逐一讨论

浏览器缓存都有哪些类型

按存储位置分类

浏览器缓存按照缓存储存位置分类,可以参考下图为Twitter主页的资源类型:

谈谈浏览器的缓存机制_第3张图片

可以看到资源类型分为四种:

  • ServiceWorker
  • memory cache 读取内存缓存资源
  • disk cache 读取本地磁盘缓存资源
  • 无缓存的正常请求

从类型上我们可以简单进行读取速度的比较(Seriveworker后面会讲):

memory cache > disk cache > 网络请求

memory cache

顾名思义: 就是浏览器内存中的缓存,因此相比读取磁盘速度更快。

思考一下,是不是所有的资源都可以存储到memory cache,那么我们的页面不就是飞速的提升?

答案是:想多了。单个页面请求数量过大,但是浏览器的占用内存又不是无限制的,势必导致memory cache是一个短期存储器

  • memory cache的生命周期也很短暂,当关闭一个tab栏时,浏览器会自动释放对应页面的缓存。

disk cache

  • disk cache就是储存在磁盘中的缓存,属于持久化存储,是真实存储在计算机的文件系统中的。
  • disk cache缓存的有效期需要通过HTTP头信息来判断(后面会讲),并且缓存过期后,不同浏览器会有自己的算法识别过期资源并进行清理。

请求网络

在前述所有的缓存中都没有命中,浏览器就会发起HTTP网络请求。

ServiceWorker

概念

这个 API 的唯一目的就是解放主线程,Web Worker 是脱离在主线程之外的,将一些复杂的耗时的活交给它干,完成后通过 postMessage 方法告诉主线程,而主线程通过 onMessage 方法得到 Web Worker 的结果反馈。

功能和特性

  • Service Worker拥有自己独立的 worker 线程,独立于当前网页线程
  • 离线缓存静态资源
  • 拦截代理请求和响应
  • 可自定义响应内容
  • 可以通过postMessage向主线程发送消息
  • 无法直接操作DOM
  • 必须在HTTPS环境下工作或 localhost / 127.0.0.1 (自身安全机制)
  • 通过Promise异步实现
  • Service Worker安装(installing)完成后,就会一直存在,除非手动卸载(unregister)

参考自: ServiceWorker 缓存离线化

优先级

当浏览器发起一个请求之后,首先会从serviceWorker中的cacheStorage中查询,如果命中则返回对应资源,没有继续从memory cache中查找,以此类推,直到所有缓存都没有命中,发起一个HTTP网络请求。

  • 首次访问页面
    谈谈浏览器的缓存机制_第4张图片

  • 刷新该页面

可以看到,对应的资源文件已经储存到memory cache
谈谈浏览器的缓存机制_第5张图片

  • 关闭tab页,重新打开该页面访问

静态资源文件已经全部从disk cache中获取
谈谈浏览器的缓存机制_第6张图片

因此,我们就可以看到三者的缓存读取的顺序了。

按缓存失效分类

按缓存失效后采取的措施,可以分为: 强缓存协商缓存

强缓存

强缓存就是本地缓存,即前文提到的disk cache。影响强制缓存的两个字段分别是: Cache-control 和 Expires。

常见的Cache-control设置有:

Cache-Control: max-age=<seconds> 设置缓存存储的最大周期
Cache-Control: max-stale[=<seconds>] 表明客户端愿意接收一个已经过期的资源
Cache-Control: min-fresh=<seconds> 表示客户端希望在指定的时间内获取最新的响应
Cache-control: no-cache  在释放缓存副本之前,强制高速缓存将请求提交给原始服务器进行验证
Cache-control: no-store 缓存不应存储有关客户端请求或服务器响应的任何内容
Cache-control: no-transform 不得对资源进行转换或转变
Cache-control: only-if-cached 表明客户端只接受已缓存的响应,并且不要向原始服务器检查是否有更新的拷贝

对比缓存

当本地缓存过期之后,请求服务端之后,服务端对比资源文件,下发304状态码,表示当前本地缓存继续可用,于是客户端继续使用缓存。这类缓存读取与本地直接读取缓存多了一次请求过程。
谈谈浏览器的缓存机制_第7张图片

对比缓存有两组字段:

Last-Modified & If-Modified-Since

  1. 服务器通过 Last-Modified 字段告知客户端,资源最后一次被修改的时间,例如 Last-Modified: Mon, 10 Nov 2018 09:10:11 GMTLast-Modified: Mon, 10 Nov 2018 09:10:11 GMT
  2. 浏览器将这个值和内容一起记录在缓存数据库中。浏览器将这个值和内容一起记录在缓存数据库中。
  3. 下一次请求相同资源时时,浏览器从自己的缓存中找出“不确定是否过期的”缓存。因此在请求头中将上次的 Last-Modified 的值写入到请求头的 If-Modified-Since 字段下一次请求相同资源时时,浏览器从自己的缓存中找出“不确定是否过期的”缓存。因此在请求头中将上次的 Last-Modified 的值写入到请求头的 If-Modified-Since 字段
  4. 服务器会将 If-Modified-Since 的值与 Last-Modified 字段进行对比。如果相等,则表示未修改,响应 304;反之,则表示修改了,响应 200状态码,并返回数据。服务器会将 If-Modified-Since 的值与 Last-Modified 字段进行对比。如果相等,则表示未修改,响应 304;反之,则表示修改了,响应 200状态码,并返回数据。
  • Etag & If-None-Match

Etag 存储的是文件的特殊标识(一般都是 hash 生成的),服务器存储着文件的 Etag 字段。之后的流程和 Last-Modified 一致,只是 Last-Modified 字段和它所表示的更新时间改变成了 Etag 字段和它所表示的文件 hash,把 If-Modified-Since 变成了 If-None-Match。服务器同样进行比较,命中返回 304, 不命中返回新资源和 200

Etag 的优先级高于 Last-Modified

你可能感兴趣的:(离线缓存,Web前端,浏览器,JavaScript篇)