HTTP缓存
浏览器缓存
缓存可以减轻服务器的压力,减少宽带,提升性能与用户体验
内存缓存(Memory Cache)
- 存储位置:存储在计算机的内存(RAM)中。
- 访问速度:访问速度非常快,通常比磁盘缓存快得多。
- 容量限制:内存容量有限,通常只能存储最近访问的资源。
- 持久性:浏览器关闭后,内存缓存中的内容会被清空。
磁盘缓存(Disk Cache)
- 存储位置:存储在计算机的硬盘(HDD/SSD)中。
- 访问速度:访问速度较慢,但比从网络重新加载资源快。
- 容量限制:磁盘缓存的容量通常较大,可以存储更多的资源。
- 持久性:即使浏览器关闭,磁盘缓存中的内容仍然保留,直到被浏览器清理。
频繁访问的资源,浏览器会优先保留在内存缓存中;不频繁访问的资源,优先存储在磁盘缓存中;内存不足时,会将不常用存到缓存移到磁盘缓存中
nginx配置缓存示例
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 7d; # 设置缓存时间为7天
add_header Cache-Control "max-age=604800, public"; # 设置强缓存
}
location ~* \.html$ {
expires off; # 不启用强缓存
}
浏览器缓存机制
如果设置了强缓存会判断缓存是否过期,没过期则直接走缓存,Network中状态码200,过期则重新请求并缓存资源;
过期则看协商缓存,如果设置了协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),会向服务器发送请求判断缓存是否生效,没过期返回304,直接走缓存,过期则返回200,并更新缓存
如果没有规定强缓存,则会走浏览器默认的启发式缓存,根据 Last-Modified和Date,判断缓存策略
浏览器缓存的分类
强缓存
请求资源的时,如果是之前请求过的并使用强缓存,那么在过期时间内将不会发送本次请求向服务器获取资源,而是直接从浏览器缓存中获取(不管资源是否改动)。过期了将重新从服务器获取,并再次强缓存。
怎么设置强缓存:
我们第一次进入页面,请求服务器,然后服务器进行响应,浏览器会根据response Header来判断是否对资源进行缓存,如果响应头中expires、pragma或者cache-control字段,代表这是强缓存,浏览器就会把资源缓存在memory cache 或 disk cache中
1》expires
是HTTP1.0控制网页缓存的字段,指定资源过期时间
如 2025.3.30 10:28 过期:
Expires: Sun, 30 Mar 2025 10:28:00 GMT
有个缺点,就是它判断是否过期是用本地时间来判断的,本地时间是可以自己修改的
2》pragma
HTTP1.0中禁用网页缓存的字段,其取值为no-cache,不走缓存
Pragma
是一个历史遗留的HTTP/1.0字段,主要用于向后兼容。
Pragma: no-cache
3》cache-control
是HTTP1.1中控制网页缓存的字段,客户端缓存资源,但是是否缓存需要经过协商缓存来验证
取值 | 说明 |
---|---|
max-age= | 资源缓存多少秒后失效; Cache-Control: max-age=3600 缓存 1 小时 |
no-cache | 强制客户端在使用缓存前,先向服务器验证资源是否有效(并不是不缓存响应内容) 服务器会根据 ETag 或 Last-Modified 来判断资源是否发生变化,没变化会返回304,变了会返回新的资源的200状态码; 适用于那些需要频繁更新或对时效性要求较高的资源,如新闻网站的首页 |
no-store | 完全禁止缓存 |
public | 示资源可以被任何缓存(如代理服务器)缓存; Cache-Control: public, max-age=3600 |
privite | 资源只能被客户端缓存,代理服务器不能缓存 |
must-revalidate | 一般和max-age一起使用; max-age=3600, must-revalidate ; 一旦缓存过期,即使用户说陈旧的响应是可以接受的,也拒绝向用户返回陈旧的响应。如果服务器不响应重新验证请求,则浏览器/代理应该返回 504 错误;而no-cache 如果服务器无法响应,客户端仍然可以使用缓存的内容 |
优先级:cache-control > pragma > expires
协商缓存
请求资源时,如果是之前请求过的并使用协商缓存,还是发送请求到服务器,服务器通过逻辑判断确认资源没有修改返回304状态码(不会返回文档的主体),那么本次的资源则是从缓存中获取;如果经过判断确认资源被修改过,则重新发送资源到客户端,并且客户端更新缓存
协商缓存就是强缓存失效后,浏览器携带缓存标识向服务器发送请求,由服务器根据缓存标识来决定是否使用缓存的过程
是否走协商缓存是根据响应头:
一、Last-Modified /If-Modified-Since
Last-Modified:服务器响应请求时,返回该资源文件在服务器最后被修改的时间
If-Modified-Since:客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件
有个问题就是以秒为单位,如果1秒内进行了多次更改,是不能够判断出来做出了更改的
二、Etag / If-None-Match
Etag:服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)
If-None-Match:客户端再次发起该请求时,携带上次请求返回的标识Etag值,服务器发现该请求头中含有If-None-Match,则会根据字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200
两者的优先级:
Etag / If-None-Match优先级高于Last-Modified / If-Modified-Since,同时存在则只有Etag / If-None-Match生效
Etag > Last-Modifed
使用方案
一般项目的缓存方案:
HTML: 协商缓存;
css、js、图片:强缓存,文件名带上has
缓存与刷新
1》当 ctrl+F5 强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存。
2》普通刷新 F5 是会走缓存的
启发式缓存
启发式缓存是一种兜底策略,当服务器没有明确指定缓存策略时,浏览器会根据资源的Last-Modified
时间和当前时间的差值,推断出一个合理的缓存时间
如果判断缓存有效,则浏览器不会将请求发送到服务器,且在Network面板的状态码是200,缓存从磁盘缓存或内存缓存中读取;因此能看到200的状态码,但是走的缓存,它实际上并没有向服务器发送请求
缓存事件:不同浏览器策略稍有不同,浏览器会根据Date和Last-Modified字段自动计算出合适的缓存时间;一般
(Date - Last-Modified) * 10%
Date指的是消息发送的时间,Last-Modified是资源上次修改的时间,只要Last-Modified保持不变,随着时间的推移,资源的缓存时间会变长
dified字段自动计算出合适的缓存时间;一般
(Date - Last-Modified) * 10%
Date指的是消息发送的时间,Last-Modified是资源上次修改的时间,只要Last-Modified保持不变,随着时间的推移,资源的缓存时间会变长
启发性缓存的不可靠性:由于是浏览器估算的结果,可能不符合服务器实际更新频率,建议始终显式设置 Cache-Control