1.什么是浏览器的缓存策略
- 浏览器缓存策略是现代
Web
开发中一项关键性能优化手段,旨在减少网络延迟、降低服务器负载以及提升用户访问速度。浏览器通过缓存策略存储网页中的静态资源,并在后续访问时尽可能地复用这些已缓存的内容,而非每次都向服务器发起新的请求。 - 优点:
- 直接从内存或磁盘中取缓存数据能加快客户端网页加载速度,减少用户等待时间,提升用户体验。
- 减少了冗余的数据传输,减少服务器的负担,提升网站性能。
2. 缓存位置与优先级
- 离线缓存
Service Worker cache
。(详情看后续文章) - 浏览器内存缓存
memory cache
。- 相比于硬盘缓存,它的特点是读取速度快,但容量小,且时效性短。一旦浏览器
tab
页关闭,浏览器内存缓存就将被清空,再次重新打开相同页面时不再出现from memory cache
的情况。 - 不受开发者控制,也不受HTTP协议头的约束,但是当
HTTP
响应头设置了Cache-Control: no-store
的时候或者浏览器开发者工具network
设置了Disabled cache
禁用缓存后,就无法把资源存入浏览器内存了,也无法存入硬盘 - 当从浏览器内存缓存中查找缓存的时候,不仅仅会去匹配资源的
URL
,还会看其Content-type
是否相同。
- 相比于硬盘缓存,它的特点是读取速度快,但容量小,且时效性短。一旦浏览器
- 硬盘缓存
disk cache
。- 从存储效率上讲是浏览器内存缓存慢的,但是优势是存储容量大和存储时间长。
- 可以根据
HTTP
响应头的各类字段进行判定资源的缓存规则,比如是否可以缓存,什么时候过期,过期之后是否需要重新发起请求
- 文件会先在浏览器内存缓存中查找,如果有,直接加载。 如果不存在,则在硬盘缓存中查找,如果有直接加载。 如果硬盘缓存中也没有,则向服务器发起网络请求。请求获取的资源缓存到硬盘和内存。
- 浏览器内存缓存适合存储脚本文件图片文件等,硬盘缓存适合存储
CSS
文件。CSS
文件加载一次就可渲染出来,不会频繁读取它,所以它不适合缓存到内存中,但是脚本却随时可能会执行,当执行脚本的时候需要从硬盘取到内存中来,这样IO
开销就很大。
3. 强缓存与协商缓存
强缓存
- 强缓存是一种完全基于客户端缓存数据来决定是否使用缓存的策略。当浏览器发起一个资源请求时,首先检查是否有对应的强缓存数据存在,并依据以
Expires
或Cache-Control
的响应头部信息判断缓存是否有效,有效的话是的话便直接从本地缓存中读取资源,不与服务器进行通信。 - 同时设置了两个字段的适合时候,
Cache-Control
优先级比Expires
高。
Expires
- 是
HTTP/1.0
时代的头部字段,它设置了一个绝对的GMT日期时间
,表示资源的过期时间。 - 若当前时间在此之前,浏览器认为缓存有效,反之则无效。由于其依赖于客户端系统时间可能与服务器设置的时间可能存在误差,现代应用中逐渐被
Cache-Control
取代。
js
Expires: Mon Oct 17 2023 16:10:32 GMT
Cache-Control
- 是
HTTP/1.1
标准中定义的响应头部字段,用于更精确地控制缓存行为。 Cache-Control: max-age=<seconds>
:用来指定资源的最大存活时间(以秒为单位)。在此期间内,浏览器认为缓存有效,无需向服务器验证,直接使用本地缓存响应请求。超过这个时间后,浏览器将重新发起请求。Cache-Control: no-store
:禁止缓存任,所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存。Cache-Control: public
:所有内容都可被缓存。Cache-Control: private
:所有内容只有客户端可以缓存,Cache-Control
的默认取值。Cache-Control: s-maxage=<seconds>
:对于共享缓存而言,优先于max-age
。仅适用于代理服务器。Cache-Control: no-cache
:缓存不直接使用,是否使用缓存则需要经过协商缓存来验证决定。除了此选项其他的都是强缓存,强缓存失效的情况下会使用协商缓存。- 强制缓存返回的状态值是
200
,size
下会显示两种字段,from memory cache
代表使用浏览器内存中的缓存。from disk cache
则代表使用的是硬盘中的缓存。
协商缓存
- 协商缓存发生在强缓存失效或未命中时,浏览器向服务器询问现有缓存资源是否仍然有效。如果强缓存失效后,客户端将向服务器发出请求,进行协商缓存。
- 浏览器会自动携带上一次请求返回的响应头中的 缓存标识 向服务器发起请求
ETag、Last-Modified
,由服务器判断资源是否更新。 - 如果资源没有更新,则返回状态码
304 Not Modified
,告诉浏览器可以使用本地缓存;否则返回新的资源内容。 - 强缓存优先级高于协商缓存,但是协商缓存可以更加灵活地控制缓存的有效性。
ETag/If-None-Match
ETag
是服务器为每个资源生成的一个唯一标识符(通常基于内容哈希或其他算法),随响应头一起发送给客户端。- 当浏览器再次请求时,浏览器会在请求头附带上
If-None-Match
头部,其值为之前接收到的ETag
- 服务器比较请求中的
If-None-Match
与当前资源的ETag
,如果二者匹配,则说明资源内容没有变化,服务器返回304 Not Modified
状态码,使用本地缓存。
Last-Modified/If-Modified-Since
Last-Modified
是服务器指示资源最后修改时间的头部字段。第一次请求是服务器响应头中携带Last-Modified
时间。- 浏览器在后续请求中自动携带
If-Modified-Since
头部,其值为之前接收到的Last-Modified
。 - 服务器比较请求头中的
If-Modified-Since
与当前资源的最后修改时间,如果Last-Modified
晚于If-Modified-Since
,说明资源已被更新,服务器返回新资源和200 OK
状态码;否则返回304 Not Modified
。
4. 缓存执行过程
- 强缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,返回状态码为
200
。 - 强缓存失效或未命中,浏览器向服务器发起请求。请求头中包含
If-None-Match
(基于ETag
)或If-Modified-Since
(基于Last-Modified
)头部,进行协商缓存。 - 服务器接收到请求,比较条件头与当前资源的状态,若资源未发生变化,服务器返回
304 Not Modified
,浏览器使用本地缓存。若资源已更新,服务器返回新资源状态码200 OK
及新的ETag
或Last-Modified
,浏览器更新缓存并使用新资源。
5. 总结
- 在实际应用中,可能同时采用强缓存和协商缓存策略。浏览器优先考虑强缓存,只有当强缓存失效或无法满足时,会进入协商缓存阶段,向服务器发起条件请求。
- 这样设计的原因在于强缓存能够避免不必要的网络通信,提供最快捷的响应体验。而协商缓存虽然仍需与服务器通信,但只需少量数据交换即可确定缓存的有效性,相比完全重新下载资源,仍能显著节省带宽和提高性能。
- 浏览器的缓存策略通过强缓存和协商缓存相结合的方式,有效地利用客户端存储减少网络交互,优化网页加载速度。