前端缓存
性能优化总少不了缓存,网页性能优化里面静态资源相关优化是少不了浏览器的缓存
强缓存
通过 两个http response header:
- Expires
- Cache-Control
Expires:
- 浏览器请求时,会把资源和response header 都缓存下来
- 再次请求这个资源时,会先在缓存中找,如果找到了,而且当前时间小于Expires中的时间,缓存命中就不会去请求服务器了。所以首当前客户端时间影响
- 如果缓存没有命中会去请求服务器,更新Expires
Cache-Control:
- 第一次请求时,会缓存资源和Response header
- 再次请求时,会先从缓存中找,找到后,根据它第一次的请求时间和Cache-Control设定的有效期,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就能命中缓存,否则就不行。
- 如果缓存没有命中,会去请求服务器,然后更新本地
Cache-Control描述的是一个相对时间,在进行缓存命中的时候,都是利用客户端时间进行判断,所以相比较Expires,Cache-Control的缓存管理更有效,安全一些。
这两个header可以只启用一个,也可以同时启用,当response header中,Expires和Cache-Control同时存在时,Cache-Control 优先级高于Expires。
协商缓存
通过两对http request/response header:
- Etag/If-None-Match
- Last-Modified/If-Modified-Since
Etag/If-None-Match:
- 第一次请求,在ResponseHeader中返回服务器根据资源生成的 Etag
- 第二次请求时,requestHeader带上If-None-Match,值为Etag,服务器接受请求时根据资源生成Etag 和If-None-Match进行比较,如果相同,表示资源没有变化,返回
304 Not Modified
,如果不同,表示资源变化了,返回新的资源
Last-Modified/If-Modified-Since:
- 第一次请求,在ResponseHeader中返回服务器根据资源生成的 Last-Modified
- 第二次请求时,requestHeader带上If-Modified-Since,值为Last-Modified,服务器接受请求时根据资源的最后修改时间 和If-None-Match进行比较,如果相同,表示资源没有变化,返回
304 Not Modified
,如果不同,表示资源变化了,返回新的资源
协商缓存跟强缓存不一样,强缓存不发请求到服务器,所以有时候资源更新了浏览器还不知道,但是协商缓存会发请求到服务器,所以资源是否更新,服务器肯定知道。大部分web服务器都默认开启协商缓存,而且是同时启用【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】,这是为了处理Last-Modified不可靠的情况。
分布式系统里多台机器间文件的Last-Modified必须保持一致,以免负载均衡到不同机器导致比对失败;
分布式系统尽量关闭掉ETag(每台机器生成的ETag都会不一样);
ServiceWorker 离线缓存
Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用 Service Worker的话,传输协议必须为 HTTPS。因为 Service Worker 中涉及到请求拦截,所以必须使用 HTTPS 协议来保障安全。Service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。
Service Worker 实现缓存功能一般分为三个步骤:
- 首先需要先注册 Service Worker
- 监听到 install 事件以后就可以缓存需要的文件
- 在下次用户访问的时候通过拦截请求的方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据。
当 Service Worker 没有命中缓存的时候,我们需要去调用 fetch 函数获取数据。也就是说,如果我们没有在 Service Worker 命中缓存的话,会根据缓存查找优先级去查找数据。但是不管我们是从 Memory Cache 中还是从网络请求中获取的数据,浏览器都会显示我们是从 Service Worker 中获取的内容。
一些疑问:
Q:同时启用【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】的优先级?
A:Etag是因为Last-Modified的一些问题,比如文件头修改了,内容没有修改等,而出现的。Etag的优先级大于Last-Modified