强缓存和协商缓存
缓存
为了减少资源请求次数,加快资源访问速度,浏览器会对资源文件如图片、css文件、js文件等进行缓存,而浏览器缓存策略又分为强缓存和协商缓存。
强缓存
强缓存是指浏览器在缓存有效期内直接从本地缓存中读取资源,而不与服务器进行任何通信。强缓存的实现依赖于 HTTP 响应头中的 Expires 或 Cache-Control。
Expires
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires
一个绝对的过期时间(GMT 时间),在此时间之前,浏览器会认为缓存是有效的。
1 | Expires: Wed, 21 Oct 2024 07:28:00 GMT |
Cache-Control
max-age代表缓存时间,单位为秒
1 | Cache-Control: max-age=3600 |
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
使用缓存的话,状态码200后面会标明情况。浏览器缓存资源的地方有两个:磁盘缓存(disk cache)和内存缓存(memory cache)。
当缓存时间到期后再次访问时,状态码200后面便没有括号内的内容了。
一般来说,浏览器会将较大的资源缓存到disk cache,而较小的资源则被缓存到memory cache里。内存缓存与磁盘缓存相比,访问速度要更快一些!
Cache-Control除了max-age外,还可以设置其它属性值:
- no-cache: 不使用强缓存(但仍会使用协商缓存)。
- no-store: 不使用缓存(不使用强缓存也不使用协商缓存),每次都向服务器发送资源请求。
- private: 只允许客户端使用缓存,不允许其他代理服务器进行缓存。
- public: 客户端和代理服务器都可缓存。
- s-maxage: 与max-age类似,区别是s-maxage是设定代理服务器的缓存时间。
另外,Cache-control的优先级要高于Expires,如果两者同时设置,会优先使用Cache-control而忽略掉Expires。
协商缓存
在强缓存里,是否使用缓存是由浏览器来确定的,而协商缓存则是由服务器来告诉浏览器是否使用缓存资源,也就是浏览器每一次都要发送请求到服务器询问是否使用缓存,协商缓存的具体流程如下:
浏览器初次请求资源,服务器返回资源,同时生成一个Etag值携带在响应头里返回给浏览器,当浏览器再次请求资源时会在请求头里携带If-None-Match,值是之前服务器返回的Etag的值,服务器收到之后拿该值与资源文件最新的Etag值做对比。
- 如果没有变化则返回304,告诉浏览器继续使用缓存(不返回资源文件)。
- 如果发生变化,则返回200和最新的资源文件给浏览器使用。
除了Etag外,还有一个Last-Modified的属性,它是Http1.0规范的,服务器返回Last-Modified,浏览器请求头对应携带的是If-Modified-since,与Etag不同的是,Last-Modified的值是一个时间值,代表文件的修改时间,服务器通过对比文件的修改时间是否发生改变来判断是否使用缓存。
相比Last-Modified,Etag优先级更高,使用上也更精确一些,因为有时候会存在文件内容并没有改变,但文件的修改时间变更了,Last-Modified不一致所以服务器会重新返回资源文件,实际上还是可以继续使用缓存的。
强缓存优先级大于协商缓存,即两者同时存在时,如果强缓存开启且在有效期内,则不会走协商缓存。
总结
强缓存就是浏览器本地根据服务器设置的过期时间来判断是否使用缓存,未过期则从本地缓存里拿资源,已过期则重新请求服务器获取最新资源。
协商缓存则是浏览器本地每次都向服务器发起请求,由服务器来告诉浏览器是从缓存里拿资源还是返回最新资源给浏览器使用。
Reference: https://juejin.cn/post/7259298281578889273?searchId=20240712153934B2B3A1160462EB235132