缓存控制
在实际应用中存在大量重复的资源获取,在获取资源时会优先进行强缓存匹配,若命中失败,则发送 HTTP 请求由服务端判断是否命中协商缓存;借助合理的缓存控制可以大幅提高资源获取效率。
缓存位置
客户端查询缓存时依据以下缓存位置的优先级进行
- Service Worker:用于 PWA,缓存可自由控制且持续
- Memory Cache:效率高,容量小,时效短(进程关闭时释放),常见于页面刷新和预加载(preloader)
- Disk Cache:效率低,容量大,时效长,客户端最常见的缓存方式
- Push Cache:HTTP2,只在会话中存在,且缓存只能被使用依次
缓存策略
通常客户端的缓存策略分为两种
- 强缓存:不会发送请求,直接从 Memory Cache 和 Disk Cache 中获取
- 协商缓存:强缓存未命中时发起请求,由服务端判断是否命中缓存
强缓存根据 Cache-Control 或 Expires 字段判断是否命中,命中时返回 200 和 from memory/disk cache
Expires: [具体时间]: HTTP1.0,存在服务端与客户端时间不一的问题Cache-Control: [指令]: HTTP1.1,优先级高于Expires,多个指令使用逗号分隔max-age=xxx: 单位秒,表示最大缓存时间s-maxage=xxx: 覆盖max-age,只在代理服务器中生效no-store: 不缓存no-cache: 资源被缓存但立即失效,下次请求时走协商缓存public: 表示响应可被客户端和代理服务器缓存private: 表示响应只可被客户端缓存max-stale=xxx: 可容忍最大过期时间,指定时间内即使过期也使用当前缓存min-fresh=xxx: 可容忍最小新鲜度,指定时间内希望获取最新响应
协商缓存根据 Last-Modified 或 Etag 字段判断是否使用缓存,命中时返回 304 和 Not Modified
Last-Modified: [具体时间]: HTTP1.1,根据资源修改时间判断是否使用缓存(存在精度、负载均衡服务器中时间不一致问题)- 客户端首次请求时,服务端在响应头添加
Last-Modified字段 - 客户端再次请求时,客户端在请求头添加
If-Modified-Since字段(值同上次返回的Last-Modified) - 服务端接收请求后,根据
If-Modified-Since与对应资源最后修改时间进行对比判断是否使用缓存
- 客户端首次请求时,服务端在响应头添加
ETag: [资源标识]: HTTP1.1,优先级更高,根据资源内容生成的唯一标识判断是否使用缓存(会有额外开销)- 服务端根据资源内容生成对应的唯一标识
- 客户端首次请求时,服务端在响应头添加
ETag字段 - 客户端再次请求时,客户端在请求头添加
If-None-Match字段(值同上次返回的ETag) - 服务端接收请求后,根据
If-None-Match与对应资源的ETag进行比对判断是否使用缓存