缓存

Web 缓存可以分为浏览器缓存、CDN 缓存、服务器缓存和数据库数据缓存这四种。其中,跟前端密切相关的是浏览器缓存。使用缓存是为了加快网页打开速度,减少网络带宽消耗,降低服务器压力等。

浏览器缓存分为强缓存和弱缓存,它们的区别是:如果强缓存命中,则不会向服务器发送请求;弱缓存一定会发送请求到服务器,通过资源的请求首部字段验证是否命中弱缓存,在命中时服务器会将请求返回但不会返回该资源的实体,而是通过 304 这个状态码告知浏览器可以从缓存中加载这个资源。

上述过程的简略流程图为:

缓存策略

浏览器如何去缓存由 HTTP 报文的首部决定:

强缓存

强缓存又称「本地缓存」。

控制强缓存的报文首部字段按照优先级排列为:

字段 说明
Pragma 在响应报文中设置为 no-cache 时,会通知浏览器不直接使用缓存,要求向服务器发请求校验新鲜度。因为它优先级最高,当存在时一定不会命中强缓存。
Cache-Control 见下表
Expires 指定了一个日期/时间,在这个时间/日期之前,HTTP 缓存被认为是有效的。

Cache-Control 与浏览器缓存相关的值主要有:

说明
private 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。响应只作为私有的缓存,不能被CDN等缓存。如果要求HTTP认证,响应会自动设置为private。
public 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存。表明响应可以被浏览器、CDN等等缓存。
no-cache 缓存前必需确认其有效性。表示请求必须先与服务器确认缓存的有效性,如果有效才能使用缓存(弱缓存),无论是响应报文首部还是请求报文首部出现这个字段均一定不会命中强缓存。Chrome硬性重新加载(Command+shift+R)会在请求的首部加上 Pragma: no-cacheCache-Control: no-cache
no-store 不缓存请求或响应的任何内容。表示禁止浏览器以及所有中间缓存存储任何版本的返回响应,一定不会出现强缓存和弱缓存,适合个人隐私数据或者经济类数据。
max-age=[s] 响应的最大值,单位为 s(秒)。设置缓存的存在时间,相对于发送请求的时间。只有响应报文首部设置Cache-Control为非0的max-age或者设置了大于请求日期的Expires(下文会讲)才有可能命中强缓存。当满足这个条件,同时响应报文首部中Cache-Control不存在no-cache、no-store且请求报文首部不存在Pragma字段,才会真正命中强缓存。

弱缓存

弱缓存又称「协商缓存」。

控制弱缓存的报文首部字段按照优先级排列为:

  1. ETag / If-None-Match
  2. Last-Modified / If-Modified-Since

缓存位置

浏览器缓存位置分为四种,其优先级顺序如下:

  1. Service Worker
  2. Memory Cache
  3. Disk Cache
  4. Push Cache

当上述四个缓存位置中的缓存都没有命中时,则会向服务器发起请求。

在 Chrome 浏览器中查看「Network」信息时会发现,「Size」那栏有的请求会显示 from disk cachefrom memory cache。在 Chrome 扩展程序的 API 文档的 chrome.webRequest 中有相关描述:

Chrome employs two caches — an on-disk cache and a very fast in-memory cache. The lifetime of an in-memory cache is attached to the lifetime of a render process, which roughly corresponds to a tab. Requests that are answered from the in-memory cache are invisible to the web request API. If a request handler changes its behavior (for example, the behavior according to which requests are blocked), a simple page refresh might not respect this changed behavior. To make sure the behavior change goes through, call handlerBehaviorChanged() to flush the in-memory cache. But don't do it often; flushing the cache is a very expensive operation. You don't need to call handlerBehaviorChanged() after registering or unregistering an event listener.

具体是什么机制尚未得知,知乎有相关问题

Service Worker

Service Worker 是一个注册在指定源和路径下的事件驱动 worker。它采用 JavaScript 控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。 我们可以通过谷歌开发者工具中的 Application -> Service Workers 查看当前缓存的资源。

Memory Cache

Memory Cache 即内存中的缓存,其特点是容量小、读取高效、持续性短,会随着进程的释放而释放。 所以,在内存使用率低、缓存小尺寸资源时,会以 Memory Cache 为优先,否则使用 Disk Cache。

Disk Cache

Disk Cache 即磁盘中的缓存,其特点是容量大、读取缓慢、持续性长,任何资源都能存储到磁盘中。 所以,在内存使用率高、缓存大尺寸资源时,会以 Disk Cache 为优先。

Push Cache

Push Cache 是 HTTP 2.0 中的内容,其缓存时间也很短暂,只在会话(Session)中存在,一旦会话结束就被释放。

更新缓存

想不修改文件路径去更新缓存是不可能的,因此要通过更新 URL 中的查询字符串或者文件名中的指纹来实现缓存的更新。

总结

浏览器获取网络资源的完整流程为:

资料

results matching ""

    No results matching ""