# 浏览器缓存
# 强缓存(不与服务器发生交互行为)
强缓存是利用http的返回头中的Expires或者Cache-Control两个字段来控制的,用来表示资源的缓存时间。
# Expires
Http1.0 中的标准
存在问题:服务器时间与客户端时间的不一致,就会导致缓存跟期待效果出现偏差
# cache-control
Http1.1 中的标准,使用的是相对时间的概念
# 可选参数
- max-age: 设置缓存的最大的有效时间,单位为秒(s)。max-age会覆盖掉Expires
- s-maxage: 只用于共享缓存,比如CDN缓存(s -> share)。与max-age 的区别是:max-age用于普通缓存,而s-maxage用于代理缓存。如果存在s-maxage,则会覆盖max-age 和 Expires
- no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
- no-store:直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
- public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。(默认值)
- private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。
# 协商缓存(服务器决定是否使用缓存)
# Last-Modify/If-Modify-Since
浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-modify是一个时间标识该资源的最后修改时间,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。
当浏览器再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。
如果命中缓存,则返回304,并且不会返回资源内容,并且不会返回Last-Modify。
# ETag/If-None-Match
与Last-Modify/If-Modify-Since不同的是,Etag/If-None-Match返回的是一个校验码。ETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化。服务器根据浏览器上送的If-None-Match值来判断是否命中缓存。
与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化。
# 缓存的不同来源(from disk/memory cache)
- 访问-> 200 -> 退出浏览器再进来-> 200(from disk cache) -> 刷新 -> 200(from memory cache).总结: 会不会是chrome很聪明的判断既然已经从disk拿来了, 第二次就内存拿吧 快。
- 只要图片是base64 我看都是from memroy cache.总结: 解析渲染图片这么费劲的事情,还是做一次然后放到内存吧
- 大型的js css文件都是直接disk cache.总结: chrome判断内容数据太多
- 隐私模式下,几乎都是 from memroy cache.总结: 隐私模式,为了安全
# 以下行为可能改变缓存的默认处理方式
当ctrl+f5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存;
当f5刷新网页时,跳过强缓存,但是会检查协商缓存;
# 禁止浏览器缓存的方法
- Expires: 告诉浏览器把回送的资源缓存多长时间 -1或0则是不缓存
- Cache-Control: no-cache
- Pragma: no-cache
- no-cache:这里不是不缓存的意思,只是每次在使用缓存之前都强制发送请求给源服务器进行验证,检查文件该没改变(其实这里和ETag/Last区别不大)
- no-store:就是禁止缓存,不让浏览器保留缓存副本
# 例题
# 很多静态文件会不断修改,如何保证浏览器总是加载到修改后的版本
# 使用HTTP头信息,制定浏览器不得缓存
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
1
2
3
2
3
# 为静态文件的URL附加版本号或hash(更常见的)
如打包工具 main.12i8901283.js, main.12312312.css