文章封面

浏览器缓存机制

发布于 2020-07-12 18:03:51阅读量 217

缓存是性能优化中简单高效的一种方式。优先的缓存策略可以缩短网页请求资源的距离,减少延迟,并且可以缓存文件进行复用,还可以减少带宽,降低网络负荷。

对于一个数据请求来说,可以分为发起请求、后端处理、浏览器响应 3 个阶段,缓存可以在 1、2 两步优化性能。

缓存位置

1. service worker

service worker 是运行在浏览器背后的独立线程。使用 service worker 必须使用 https 传输协议。service worker 可以让用户自由控制缓存哪些文件,如何匹配缓存、如何读取缓存,同时缓存还是持久性的。

2. Memory Cache

memory cache 是内存中的缓存,主要包含当前页面中已经抓取到的资源。

3. Disk Cache

disk cache 是硬盘中的缓存。

4. Push Cache

Push Cache 是推送缓存,是 HTTP/2 中的内容,当以上 3 种缓存都没有命中时,才会被使用。该缓存在 会话(session)中存在,会话结束就会被释放。

小结

通常浏览器缓存分为 2 种:强缓存 和 协商缓存,并且缓存策略都是通过设置 HTTP Header 实现的。

缓存过程

  • 浏览器每次发起请求,都会现在浏览器缓存中查找请求的结果和标识
  • 浏览器每次拿到返回的请求都会将该结果和缓存标识存入缓存中

强缓存

强缓存:不会向服务器发生请求,直接从缓存中读取资源。在 chrome 控制台可以看到该请求返回 200 的状态码,并且 size 显示 from disk cache 或 from memory cache。 强缓存可以通过设置 2 中 HTTP Header 实现:expires 和 Cache-Control。

  • expires
    缓存过期时间,用来指定资源到期时间,是服务器的具体的时间点。expires=max-age + 请求时间,需要和 last-modified 结合使用。expires 是 HTTP/1 的产物,受限于本地时间,修改本地时间,可能会导致缓存失效。
  • cache-control
    cache-control 可以在请求头或响应头中设置,可以组合使用多种指令。
    • public:所有内容都会被缓存
    • private: 所有内容只有客户端可以缓存
    • no-cache: 不是说浏览器不使用缓存,而是先确认下数据和服务器是否一致。也就是使用 etag 或者 last-modified 控制缓存。
    • no-store:所有内容都不缓存,不使用强缓存也不使用协商缓存
    • max-age: 表示缓存内容在多久后失效
    • s-maxage: 同 max-age,但是只在代理服务器生效(比如 cdn)
    • max-stale: 能容忍的最大过期时间
    • max-fresh: 能容忍的最小新鲜度

expires 是 HTTP 1.0 的产物,cache-control 是 HTTP 1.1 的产物,两者同时存在时,cache-control 优先级高些。

协商缓存

强缓存判断缓存是否超出某个时间或者范围,但是不关心服务器是否已经更新内容。为了获取服务器更新,就需要使用协商缓存。

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器决定是否使用缓存。主要有 2 中情况:

  • 协商缓存生效,返回 304 和 no modified
  • 协商缓存失效,返回 200 和 请求结果

协商缓存通过 2 中 HTTP Heeader 设置:last-modified 和 etag。

last-modified 和 if-modified-since

浏览器在第一次访问资源时,服务器返回资源的同时,在 响应头添加 last-modified,值是这个资源在服务器上的最后修改时间。

浏览器下一次请求,服务器检测到 last-modified 的值,再添加个 if-modified-since 值是 last-modified 的值。服务器再次收到请求,会根据 last-modified-since 的值于服务器中这个资源的最后修改时间对比。相同 304,如果 if-modified-since 的值比服务器上资源最后修改时间小,返回新的资源和 200。

last-modified 存在的弊端:

  • 如果在本地打开缓存文件,即使没有改内容,last-modified 也会被修改,服务器就不能命中缓存
  • last-modified 只能以秒计时,如果在不可感知的时间内修改,服务器还是会认为命中缓存了

因为根据文件修改时间决定缓存命中有欠缺,所以根据文件内容是否修改, HTTP 1.1 出现了 etag 和 if-none-match。

etag 和 if-none-match

etag 是服务器响应请求时,返回当前资源文件的一个唯一标识(有服务器生成),只要资源有变化,etag 就会重新生成。

浏览器下一次请求时,只需要把上一次 etag 的值写到 if-none-match 中,服务器再比较 if-none-match 和当前资源的 etag 是否一致。

对比

精度上,etag 优于 last-modified。

Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。

  • 在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
  • 在优先级上,服务器校验优先考虑Etag

小结

强缓存优先于协商缓存,若强缓存生效则直接使用缓存,若不生效使用协商缓存(last-modified/if-modified-since 和 etag/if-none-match)。协商缓存由服务器决定是否使用缓存。使用缓存返回 304,不使用 返回 200 和 新的资源。

应用

频繁变动的资源

cache-control: no-cache

通过设置 no-cache 使浏览器每次都请求服务器,然后配合使用 etag 或者 last-modified 协商缓存。

不常变化的缓存

cache-control: max-age=315360000

通过设置一个很大的过期时间,浏览器就会使用强缓存。而为了解决更新的问题,就需要在文件名(或者路径)中添加 hash, 版本号等动态字符,之后更改动态字符,从而达到更改引用 URL 的目的,让之前的强制缓存失效 (其实并未立即失效,只是不再使用了而已)。

用户行为对浏览器缓存的影响

  • 打开网页,输入URL:查找 disk-cache,有就用,没有发请求
  • F5 刷新:优先查找 memory-cache ,然后 disk-cache
  • ctrl+ f5 (强制刷新):浏览器不使用缓存,所有请求头加上 cache-control: no-cache

发布时间:2020-07-12 18:03:51

版权信息:非商用-署名-自由转载

推荐阅读

暂无推荐

    评论

    编辑器努力加载中...