浏览器缓存机制有四个方面,它们按照获取资源时请求的优先级依次排列以下:前端
1.Memory Cache数据库
2.Service Worker Cache浏览器
3.HTTP Cache缓存
4.Push Cache性能优化
MemoryCache,是指存在内存中的缓存。从优先级上来讲,它是浏览器最早尝试去命中的一种缓存。从效率上来讲,它是响应速度最快的一种缓存。服务器
不过当页面关闭时,内存里的数据也就没有了。网络
资源存不存内存,浏览器秉承的是“节约原则”。咱们发现,Base64 格式的图片,几乎永远能够被塞进 memory cache,这能够视做浏览器为节省渲染开销的“自保行为”;此外,体积不大的 JS、CSS 文件,也有较大地被写入内存的概率——相比之下,较大的 JS、CSS 文件就没有这个待遇了,内存资源是有限的,它们每每被直接甩进磁盘。session
Service Worker 是一种独立于主线程以外的 Javascript 线程。它能够帮咱们实现离线缓存、消息推送和网络代理等功能。前端性能
一般咱们若是要使用 Service Worker 基本就是如下几个步骤:性能
在页面发起 http 请求时,service worker 能够经过 fetch 事件拦截请求,而且给出本身的响应。
页面和 serviceWorker 之间能够经过 posetMessage() 方法发送消息,发送的消息能够经过 message 事件接收到。
Service Worker 必须以 https 协议为前提。
HTTP 缓存分为强缓存和协商缓存。优先级较高的是强缓存,在命中强缓存失败的状况下,才会走协商缓存。
强缓存指的是向浏览器缓存查找该请求的结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程
强缓存是利用http响应头中的 Expires
和 Cache-Control
两个字段来控制的。
实现强缓存,过去咱们一直用 expires
。
在服务器的响应头里,会将过时时间写入 expires 字段:
那么,当咱们试图再次向服务器请求资源时,浏览器就会先对比本地时间和 expires 的时间,若是本地时间小于 expires 设定的过时时间,就直接去缓存中取这个资源。
不过expires依赖于本地时间,若是服务端和客户端的时间设置不一样,那么expires 将没法达到咱们的预期。
考虑到 expires 的局限性,HTTP1.1 新增了 Cache-Control 字段来完成 expires 的任务。当 Cache-Control 与 expires 同时出现时,咱们以 Cache-Control 为准。
Cache-Control 包含如下几个值:
(1)max-age
cache-control: max-age=31536000
max-age 会等于一个时间长度(以秒为单位)。在本例中,max-age 是 31536000 秒,它意味着该资源在 31536000 秒之内都是有效的,完美地规避了时间戳带来的潜在问题。
在代理服务器中,咱们使用 s-maxage 来执行 max-age 的功能。
(2)public 与 private
若是咱们为资源设置了 public,那么它既能够被浏览器缓存,也能够被代理服务器缓存(也就是多个用户能够共享这个缓存);若是咱们设置了 private,则该资源只能被浏览器缓存。
private 为默认值。
但多数状况下,public 并不须要咱们手动设置,由于设置了 max-age 就表示响应是能够缓存的。
(3)no-store 与 no-cache
若是咱们为资源设置了 no-cache,浏览器会对响应进行缓存,可是须要到服务器去确认这个缓存是否能用。即走咱们下文即将讲解的协商缓存的路线。
若是设置了 no-store ,全部内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
协商缓存指的是强制缓存失效后,浏览器向服务器询问缓存的相关信息,进而判断是从新发起请求仍是从本地拿缓存的过程。
若是服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存,这种状况下网络请求对应的状态码是 304(以下图)。
一样,协商缓存的标识也是在响应报文的HTTP头中和请求结果一块儿返回给浏览器的,控制协商缓存的字段分别有:Last-Modified / If-Modified-Since和Etag / If-None-Match,其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高。
若是咱们启用了协商缓存,Last-Modified 会在首次请求时随着响应头返回:
Last-Modified: Fri, 27 Oct 2017 06:35:57 GMT
随后咱们每次请求时,会带上一个叫 If-Modified-Since 的时间戳字段,它的值正是上一次 response 返回给它的 last-modified 值:
If-Modified-Since: Fri, 27 Oct 2017 06:35:57 GMT
服务器接收到这个时间戳后,会比对该时间戳和资源在服务器上的最后修改时间是否一致,从而判断资源是否发生了变化。若是发生了变化,就会返回一个完整的响应内容,并在响应头中添加新的 Last-Modified 值;不然,返回如上图的 304 响应,响应头不会再添加 Last-Modified 字段。
Etag 是由服务器为每一个资源生成的惟一的标识字符串,这个标识字符串是基于文件内容编码的,只要文件内容不一样,它们对应的 Etag 就是不一样的。
当首次请求时,咱们会在响应头里获取到一个最初的标识符字符串:
ETag: W/"2a3b-1602480f459"
那么下一次请求时,请求头里就会带上一个值相同的、名为 if-None-Match 的字符串供服务端比对:
If-None-Match: W/"2a3b-1602480f459"
不过 Etag 的生成过程须要服务器额外付出开销,会影响服务端的性能。
根据上文所说的 HTTP 缓存知识点,咱们在面对一个具体的缓存需求时,能够根据下图的路线来决策:
当咱们的资源内容不可复用时,直接为 Cache-Control 设置 no-store,拒绝一切形式的缓存;不然考虑是否每次都须要向服务器进行缓存有效确认,若是须要,那么设 Cache-Control 的值为 no-cache;不然考虑该资源是否能够被代理服务器缓存,根据其结果决定是设置为 private 仍是 public;而后考虑该资源的过时时间,设置对应的 max-age 和 s-maxage 值;最后,配置协商缓存须要用到的 Etag、Last-Modified 等参数。
Push Cache 是指 HTTP2 在 server push 阶段存在的缓存。
CDN (Content Delivery Network,即内容分发网络)指的是一组分布在各个地区的服务器。这些服务器存储着数据的副本,所以服务器能够根据哪些服务器与用户距离最近,来知足数据的请求。 CDN 提供快速服务,较少受高流量影响。
CDN 的核心点有两个,一个是缓存,一个是回源。
“缓存”就是说咱们把资源 copy 一份到 CDN 服务器上这个过程,“回源”就是说 CDN 发现本身没有这个资源(通常是缓存的数据过时了),转头向根服务器(或者它的上层服务器)去要这个资源的过程。
CDN 每每被用来存放静态资源,就是像 JS、CSS、图片等不须要业务服务器进行计算即得的资源。
Web Storage 是 HTML5 专门为浏览器存储而提供的数据存储机制。存储容量能够达到 5-10M 之间。它又分为 Local Storage 与 Session Storage。
二者的区别在于生命周期与做用域的不一样。
(1)存储数据
localStorage.setItem('user_name', 'xiuyan') sessionStorage.setItem('key', 'value');
Web Storage只能存字符串。
(2)读取数据
localStorage.getItem('user_name') var data = sessionStorage.getItem('key');
(3)删除某一键名对应的数据
localStorage.removeItem('user_name') sessionStorage.removeItem('key');
(4)清除全部数据
localStorage.clear() sessionStorage.clear();
Local Storage 的特色之一是持久,有时咱们更倾向于用它来存储一些内容稳定的资源。好比图片内容丰富的电商网站会用它来存储 Base64 格式的图片字符串,有的网站还会用它存储一些不常常更新的 CSS、JS 等静态资源。
Session Storage 更适合用来存储生命周期和它同步的会话级别的信息。这些信息只适用于当前会话,当你开启新的会话时,它也须要相应的更新或释放。好比微博的 Session Storage 就主要是存储你本次会话的浏览足迹。
IndexDB 是一个运行在浏览器上的非关系型数据库。