浏览器缓存机制
- 浏览器在发送请求前先判断是否命中强缓存
- 命中则不发送请求直接使用缓存,否则进行下一步
- 浏览器发送请求后会由服务器判断是否命中协商缓存
- 命中则从缓存获取资源,否则进行下一步
- 浏览器直接使用服务器返回的资源并更新缓存
强缓存(200 OK)
Expires
是服务器告诉浏览器的缓存过期时间(值为GMT
时间,即格林尼治时间)HTTP1.0
的产物- 受本地时间影响
- 设置的值为
max-age=xxx
(xxx 是 秒)
Cache-Control
用于控制缓存的行为- 是
HTTP1.1
的产物 - 取值
public
:允许被客户端和代理服务器缓存private
:只允许被客户端缓存(默认值)no-cache
:允许被客户端和代理服务器缓存,但在使用缓存时需要经过协商缓存来验证决定no-store
:所有内容都不会被缓存,即不使用强制缓存也不使用协商缓存每次请求都会下载完整的资源maxage=xxx
:设置客户端和代理服务器的缓存时间,表示缓存内容将在 xxx 秒后失效s-maxage=xxx
:设置代理服务器的缓存时间(优先级比max-age
高)
- 是
Cache-Control 注意点
no-cache
名字存在误导,其并不是不缓存数据,只是在使用缓存时需要经过协商缓存来验证决定max-age=0
和 no-cache
效果一致
缓存位置
- 内存缓存(memory cache)
- 快速读取(内存缓存将编译解析后的文件,直接存入该进程的内存中,占据该进程一定的内存资源,以方便下次运行使用时的快速读取)
- 进程关闭时数据会被清除
- 不请求网络资源,资源存在内存中一般
JS
和图片文件会存入内存 - 状态码:
200(from memory cache)
- 硬盘缓存(disk cache)
- 写入硬盘文件进行
I/O
操作 - 进程关闭时数据不会被清除
- 速度比
memory cache
慢 - 不请求网络资源,资源存在磁盘中一般非脚本会存在磁盘中,如
css
- 状态码:
200(from disk cache)
- 写入硬盘文件进行
- 代理服务器缓存(server worker)
- 可以拦截处理页面的所有网络请求
- 仅
HTTPS
下可用、存在兼容问题 - 状态码:
200(from service worker)
协商缓存(304 Not Modified)
Last-Modified
和 If-Modified-Since
Last-Modified
表示资源的最后修改时间,值为 GMT
格式时间字符串,精确到秒
- 浏览器第一次请求时,服务器会在响应头中返回请求资源的上次更新时间
Last-Modified
- 当浏览器再次请求时,会在请求头中携带
If-Modified-Since
值为上次请求返回的Last-Modified
- 服务器收到请求后,会根据请求头中的
If-Modified-Since
和该资源在服务器的最后被修改时间做对比- 大于
If-Modified-Since
重新返回资源文件,状态码为 200 - 小于
If-Modified-Since
资源无更新继续使用缓存文件,状态码为 304
- 大于
Last-Modified 存在的问题
- 时间精度为秒级会出现误差情况,对文件修改精度有严格要求的场景不能满足
- 在集群服务器上各个服务器上的文件时间可能不同
- 如果用旧文件覆盖新文件,因为时间更前浏览器不会请求旧文件
- 编辑了文件但未修改,会导致缓存失效
ETag 和 If-None-Match
ETag
是服务器通过算法对资源内容计算出的一个唯一标识(文件 hash
)其有强弱之分
- 强
Etag
ETag: "<etag_value>"
- 资源发生任何改变都会立刻更新
- 难生成,利于比较
- 弱
Etag
(使用W/
标识)ETag: W/"<etag_value>"
- 只在资源发生本质变化时更新
- 易生成,不利于比较
过程
- 浏览器第一次请求时,服务器会在响应头中返回当前资源文件的一个唯一标识
ETag
- 当浏览器再次请求时,会在请求头中携带
If-None-Match
值为上次请求返回的ETag
- 通过接收的
ETag
和服务器重新生成的ETag
进行对比- 不一致 重新返回资源文件,状态码为 200
- 一致 资源无更新继续使用缓存文件,状态码为 304
Last-Modified 和 Etag 对比
- 精确度上:
Etag
优于Last-Modified
- 性能上:
Etag < Last-Modified
每次生成ETag
都需要进行读写操作,而Last-Modified
只需要读取操作 - 优先级:服务器校验优先考虑
Etag
(先判断Etag
是否变化,如果Etag
没有变化再判断Last-Modified
)
应用场景
强缓存 | 协商缓存 |
---|---|
不常变化的文件 带 hash 值的 css js 图片 | 频繁变动的文件 html 文件 |
用户行为对缓存的影响
- 地址栏输入
- 查找
disk cache
(磁盘缓存)中是否有匹配,有则使用缓存,没有则发送网络请求
- 查找
- 普通刷新(F5)
- 因为浏览器
tab
标签并没有关闭,因此memory cache
(内存缓存)是可用的,会被优先使用,其次使用disk cache
(磁盘缓存) - 跳过强缓存规则,直接走协商缓存
- 因为浏览器
- 强制刷新(Ctrl + F5)
- 浏览器不使用缓存,因此发送的请求头部均带有
Cache-control: no-cache
(为了兼容还带了Pragma: no-cache
)服务器直接返回 200 和最新内容。 - 跳过所有缓存规则
- 浏览器不使用缓存,因此发送的请求头部均带有