我理解的浏览器缓存策略

浏览器资源缓存策略

浏览器的缓存大体分为四个方面html

  • Memory Cache(disk Cache)
  • Service Worker Cache
  • HTTP Cache
  • Push Cache

HTTP Cache

  • 浏览器在请求资源前会优先检测本地是否有命中强缓存。
  • 强缓存分expires与Cache-Control两种。
  • 若是命中强缓存则会向 memory cache或disk cache等多种缓存中去获取。
  • 若是没有命中则会向服务端去请求资源。 HTTP缓存分为强缓存与协商缓存强缓存使用expires与Cache-Control等属性来控制

强缓存

expires

expires是HTTP/1.0时期提出的,主要是由服务端设置过时时间,而后浏览器经过对比本地时间与expires来肯定资源是否过时是否是须要向服务端去索取资源。前端

expires: Wed, 11 Sep 2019 16:12:18 GMT

复制代码

缺点: expires是经过浏览器本地时间来对比的,若是人为的修改本地时间会致使资源缓存强缓存命中失败,从新去获取资源git

Cache-Control

Cache-Control是HTTP/1.1做为expires全面的代替者提出的,经过对Cache-Control设置不一样属性来进行资源缓存的断定github

其属性值有浏览器

  • no-cache: 数据内容不能被浏览器缓存, 每次请求都从新访问服务器确认是否过时(进行协商缓存), 如有max-age, 则缓存期间不访问服务器.
  • no-store: 浏览器、服务器、代理服务器等所有不能缓存,
  • private(默认): 只能在浏览器中缓存, 只有在第一次请求的时候才访问服务器, 如有max-age, 则缓存期间不访问服务器.
  • public: 能够被任何缓存区缓存, 如: 浏览器、服务器、代理服务器等
  • max-age: 相对过时时间, 即以秒为单位的缓存时间.
  • s-max-age: 与max-age类似,二者同时存在时优先使用s-max-age,并只在代理服务器使用且只对public有效
  • no-cache, private: 打开新窗口时候从新访问服务器 , 若设置max-age, 则缓存期间不访问服务器.
  • private, 正数的max-age: 后退时候不会访问服务器
  • no-cache, 正数的max-age: 后退时会访问服务器
cache-control: max-age=3600, s-maxage=31536000
复制代码

若是只设置了max-age,默认会采起public模式模式能够被全缓存的缓存

协商缓存

协商缓存是浏览器与服务器之间的通信,浏览器向服务器询问相关信息,肯定本地文件是否过时是否须要向服务器从新获取资源,若是资源没有变更则会重定向至浏览器端而且此时的Status Code为304 Not Modified性能优化

那么协商缓存缓存是怎么实现的呢?

  • 经过Last-Modified与ETag来进行

Last-Modified

当cache-control为no-cahce时在响应头上会带上Last-ModifiedETag,同时Last-Modified是一个时间戳。bash

而且浏览器会在随后的请求的请求头上都携带上 If-Modified-Since,这个If-Modified-Since也是一个时间戳,而这个 If-Modified-Sincee也正是上次请求的资源中携带过来的 Last-Modified,这个时候服务器会对比该资源的时间戳跟服务器上的资源的时间戳是否同样,若是一致则返回304,重定向让浏览器在缓存中取得,若是不一致则从新返回文件。

可是一样这样也是有弊端的

  • 若是修改了文件可是没有修改内容,这样文件的修改时间一样会发生变化,一样触发校验时则会致使触发一次资源的从新请求
  • 由于Last-Modified与If-Modified-Since都是使用时间戳来设置的,只要修改保存的时间足够快在100ms内完成了改动,则时间戳并不会变化,使得在校验时没法检验出变化,没有对新资源进行请求。

为了解决这样的问题,ETag也做为Last-Modified的增强与补充出现了服务器

ETag

ETag是服务器给资源生成的标识字符串,做为Last-Modified的增强与补充,他跟Last-Modified工做原理很类似,在资源的响应头中生成ETag,在后续请求的请求头中会生成If-None-Match,经过比对二者的差别,若是Last-Modified与ETag同时存在时,对ETag进行优先断定异步

一样ETag也是有其弊端,不一样于文件修改系统默认会记录其修改的时间,ETag的生成是须要额外的开销,大量的资源生成会影响性能,若是没有特殊要求使用Last-Modified已经能够知足大多数需求了。

(对ETag与Last-Modified的补充)

Nginx下配置Last-Modified时(ETag是可配置的) Apache默认是二者都会返回

那么问题来了ETag做为Last-Modified的强化与补充若是只有ETag是否也会触发交互? 结果是:ETag能够单独使用,与服务端进行资源断定

HTTP缓存指南

那对于这些资源设置应该是怎么样的呢?咱们这里参考一下Chrome给出的流程图

首先咱们须要确认资源是否是须要复用?若是不复用则将 cache-control设置为 no-store,若是须要复用则将 cache-control设置为 no-cache,随后咱们根据资源是否是须要被代理服务器缓存来设置 public或者 private,最后再设置 max-age;最后在设置 Last-ModifiedETag等属性。

MemoryCache与DiskCache

MemoryCache:在服务器内存空余的时候优先使用Memory Cache随后才会考虑使用disk Cache, 由于Memory Cache读取速度是最快的同时也是最短命的在浏览器关闭该页面时就会销毁资源,disk Cache读取速度比Memory Cache要慢可是因为它是存在硬盘中的因此它的存在时间是最长的也是最稳定的。

如图在我关闭原有页面后从新打开该页面,没有从memory cache中去获取的资源,都是从disk cache中去获取的

Service Worker Cache

上面介绍了httpcache又介绍了memoryCache,如今来介绍一下一个更陌生的service worker cache。 咱们书写的js代码一般是在主线程运行,能够访问DOM与Windows全局变量,Service Worker与Web Worker则是独立于主线程的JavaScript线层,由于他被设计成彻底异步的,因此她不会阻塞页面渲染也不会阻塞JavaScript主流程的执行因此咱们能够用它去缓存离线资源,推送消息等。 同时Service Worker对协议也是有要求的,必须是https,可是这个对于咱们本地调试或者开发实际上是不友好的,不过还算Service Worker还算是人性化,能够再localhost跟127.0.0.1环境下运行,同时github也能够执行相关的代码。 这里咱们准备一个demo

咱们启一个服务器(这里我推荐使用live-server) 页面第一次打开时Application下的cache Storage是没有任何文件的,可是在看到控制台中显示

ServiceWorker registration successful with scope:  http://127.0.0.1:8080/
复制代码

再看cache Storage,则会对出一条数据,他就是用于存储本地文件, 咱们从新请求页面会发现serviceWorker.html文件是从serviceworker中获取的

Push Cache

【持续更新中....】

参考文献 借助Service Worker和cacheStorage缓存及离线开发 前端性能优化原理与实践

相关文章
相关标签/搜索