# HTTP缓存
合理的请求缓存能优化性能! 缓存分为强缓存和协商缓存
# 浏览器缓存位置
- Service Worker
让 JS 运行在主线程之外,脱离了浏览器的窗体,常见的有离线缓存
、消息推送
和网络代理
。
- Memory Cache
内存缓存,效率最快,但是存活时间短,当渲染进程结束后,内存缓存就不存在了。
- Disk Cache
磁盘缓存,存取效率比内存缓存慢,存活时间长、存储容量大。
比较大的JS、CSS文件会存到磁盘,反之在内存;内存使用率较高的时候,文件优先进入磁盘。
- Push Cache
推送缓存,HTTP/2的内容。
# 强缓存
不需要发送HTTP请求,通过检查相应的字段判断,HTTP/1.0使用的是Expires,HTTP/1.1使用的是Cache-Control。
- Expires
即过期时间,存在于服务端返回的响应头中,告诉浏览器在这个过期时间之前可以直接从缓存里面获取数据,无需再次请求
Expires: Wed, 07 Apr 2021 01:21:20 GMT
表示资源在2021年4月7日01:21:20过期,过期了就需要向服务端发请求。
存在的问题:浏览器和服务器的时间不一致,因此时间就可能不准确。
- Cache-Control
Cache-Control采用过期时长控制缓存,对应的是max-age
Cache-Control: max-age=3600
表示响应在3600秒后失效,也就是一个小时内都可以使用缓存。
max-age还有其他属性
public: 客户端和代理服务器都可以缓存
private: 只有浏览器能缓存,中间的代理服务器不能缓存
no-cache: 跳过当前的强缓存,发送HTTP请求,即直接进入协商缓存阶段
no-store: 不进行任何形式的缓存
s-maxage: 类似max-age,但是这个是针对代理服务器的缓存时间
must-revalidate: 一旦缓存过期,必须回到资源服务器验证
2
3
4
5
6
- 注意
当Expires和Cache-Control同时存在的时候,Cache-Control会优先考虑。
强缓存失效了,就会进入协商缓存。
# 协商缓存
强缓存失效之后,浏览器在请求头中携带相应的缓存tag来向服务器发请求,由服务器根据这个tag,来决定是否使用缓存。
- Last-Modified
即最后修改时间,在浏览器第一次给服务器发送请求后,服务器会在响应头中加上这个字段。
浏览器接收到后,如果再次请求,会在请求头中携带If-Modified-Since
字段,这个字段的值也就是服务器传来的最后修改时间。
服务器拿到请求头中的If-Modified-Since
的字段后,会跟这个服务器中该资源的最后修改时间对比:
- 如果请求头中的这个值小于最后修改时间,说明是时候更新了。返回新的资源,跟常规的HTTP请求响应的流程一样。
- 否则返回304,告诉浏览器直接用缓存。
- ETag
服务器给当前文件的内容的唯一标识,只有内容变动,ETag
才会变。
浏览器接收到ETag
的值,会在下次请求时,将这个值作为If-None-Match
这个字段的内容,并放到请求头中,然后发给服务器。
服务器接收到If-None-Match
后,会跟服务器上该资源的ETag
进行对比:
- 如果两者不一样,说明要更新了。返回新的资源,跟常规的HTTP请求响应的流程一样。
- 否则返回304,告诉浏览器直接用缓存。
- 注意
- 在精准度上,
ETag
优于Last-Modified
。ETag
是按照内容给资源上标识,因此能准确感知资源的变化。而Last-Modified
就不一样了,它在一些特殊的情况并不能准确感知资源变化,主要有两种情况:
1. 编辑了资源文件,但是文件内容并没有更改,这样也会造成缓存失效。
2. Last-Modified 能够感知的单位时间是秒, 如果文件在 1 秒内改变了多次,
那么这时候的 Last-Modified 并没有体现出修改。
2
3
在性能上,
Last-Modified
优于ETag
,也很简单理解,Last-Modified
仅仅只是记录一个时间点,而ETag
需要根据文件的具体内容生成哈希值。如果两种方式都支持的话,服务器会优先考虑
ETag
。
← 加速Github访问 HTTP/2 →