浏览器缓存机制详解
在前端开发中,一个比较重要环节性能优化,然而利用浏览器缓存是性能优化中简单高效的一种优化方式了,一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷
介绍
浏览器缓存主要从以下3点进行讲解:
- 强缓存
- 协商缓存
- 缓存位置
理解以上3点,对于日常面试应该可以和面试官吹吹🐂了😊😊😊😊
强缓存
浏览器缓存分需要发Http
请求和不需要发Http
请求两种,如果命中强缓存属于不发Http
请求,如果没有命中会进行Http
请求,但是也会分两种情况,下面会介绍的协商缓存机制,就是要发请求情况。
先看下面一张请求截图
截图上面标红两个字段expires
和cache-control
,浏览器就是通过这个两个字段进行强缓存判断
Expires
在HTTP/1.0
时,浏览器判断是否命中强缓存事通过expires
字段
Expires
即过期时间,存在于服务端返回的响应头中,告诉浏览器在这个过期时间之前可以直接从缓存里面获取数据,无需再次请求
上面截图中: expires
表示在2020-01-8 07:18:24
之前都使用缓存数据,如果超过这个时间就需要发送请求向服务器请求数据
使用这种方式会有个问题如果服务器时间和浏览器时间不一样就会出现问题,所以在HTTP/1.1
中使用了新的字段来进行判断cache-control
Cache-control
在HTTP/1.1
时,浏览器判断是否命中强缓存事通过cache-control
字段
cache-control
采用过期时长来控制缓存,对应的字段如上面截图是max-age
字段
上面截图中: cache-control
中max-age
表示资源会在4320910
秒之后失效,失效之后会向服务器发送请求
如上面截图中还有个s-maxage
字读是什么意思?,下面详细介绍其中有哪些字段和具体是什么意思
- s-maxage: 针对代理服务器的缓存时间
- public: 客户端和代理服务器都可以缓存
- private: 只有浏览器能缓存了,代理服务器不能缓存
- no-cache: 跳过当前的强缓存,发送HTTP请求,即直接进入协商缓存阶段
- no-store: 不进行任何缓存
Tips: 如果cache-control
和expires
同时出现,服务器会优先使用cache-control
字段进行判断
协商缓存
强缓存失效之后,浏览器在请求头中携带相应的缓存tag
来向服务器发请求,由服务器根据这个tag,来决定是否使用缓存,这就是协商缓存
缓存tag
分为两种: Last-Modified 和 Etag
Last-Modified
即最后修改时间。在浏览器第一次给服务器发送请求后,服务器会在响应头中加上这个字段
浏览器接收到后,如果再次请求,会在请求头中携带If-Modified-Since
字段,服务器拿到字段后,会和这个服务器中该资源的最后修改时间对比,对比规则如下:
- 如果请求头中的这个值小于最后修改时间,说明是时候更新了。返回新的资源,跟常规的HTTP请求响应的流程一样
- 否则返回304,告诉浏览器直接用缓存
ETag
ETag
是服务器根据当前文件的内容,给文件生成的唯一标识的哈希值,只要里面的内容有改动,这个值就会变。服务器通过响应头把这个值给浏览器
浏览器接收到ETag
的值,会在下次请求时,将这个值作为If-None-Match
这个字段的内容,并放到请求头中,服务器会根据这个值进行对比,对比规则如下:
- 如果两者不一样,说明要更新了。返回新的资源,跟常规的HTTP请求响应的流程一样
- 否则返回304,告诉浏览器直接用缓存
两者对比
-
在准确度上,
ETag
优于Last-Modified
,ETag
是监听资源文件是否修改,只要编辑了文件都算修改过,而Last-Modified
就不一样了,它在一些特殊的情况并不能准确感知资源变化,主要有两种情况:- 编辑了资源文件,但是文件内容并没有更改,这样也会造成缓存失效。
Last-Modified
能够感知的单位时间是秒,如果文件在 1 秒内改变了多次,那么这时候的Last-Modified
并没有体现出修改了。
-
在性能上,
Last-Modified
优于ETag
,Last-Modified
仅仅只是记录一个时间点,而Etag
需要根据文件的具体内容生成哈希值。
**Tips:**如果两种方式都支持的话,服务器会优先考虑ETag。
缓存位置
如果浏览器命中缓存,那缓存文件到底存储在哪里?浏览器缓存位置主要有以下几个位置:
- Service Worker
- Memory Cache
- Disk Cache
- Push Cache
Service Worker
对Service Worker
详细介绍请查看另一篇文章Service Worker
其中Service Worker Cache
就是我们使用的离线缓存
Memory Cache
Memory Cache指的是内存缓存,速度是最快的,但是保存时间也是最短的
Disk Cache
Disk Cache指的是磁盘存储,存储时间慢,但是保存时间是最长的
Push Cache
Push Cache指的是推送缓存,参考文章Creating a Cache-aware HTTP/2 Server Push Mechanism
缓存流程
- 首先判断是否命中强缓存(
Cache-Control
和Expires
) - 如果强缓存可用,直接使用
- 否则进入协商缓存,即发送
HTTP
请求,服务器通过请求头中的Last-Modified
或者ETag
字段检查资源是否更新 - 若资源更新,返回资源和200状态码
- 否则,返回304,告诉浏览器直接从缓存获取资源
下面截图是浏览缓存机制流程图: