缓存简述
1.概念
每当我们输入网址时浏览器负责通过http协议向服务器请求获取数据,缓存可以缩短请求时间,节省带宽,对于缓存文件重复利用,利用缓存机制可以提升优化性能和体验。请求资源可以分为如下三步:发起网络请求,后端服务器处理,浏览器响应。缓存则是在第一次请求时将请求到的资源进行本地保存,下次发起同样请求时如果缓存策略判定本地资源和服务器资源一致,则浏览器直接读取缓存资源渲染给用户。
2.缓存位置
- ServerWorker是运行在浏览器背后的独立线程,用于实现缓存功能,使用ServerWorker时传输协议必须是HTTPS,可以自由控制缓存文件,如何匹配,并且缓存资源是带有持续性;
- MemoryCache内存缓存,文件储存于内存读取较快,但是缓存持续时间短,进程标签页被关闭时内存中的缓存将被释放;
- DiskCache硬盘缓存,读取数据较慢,根据HTTP请求头字段判定资源是否缓存;
- PushCache推送缓存,属于HTTP/2规范内容;
3.请求缓存场景
浏览器和服务器的通信方式是应答模式,是否有这样的疑惑,浏览器发起HTTP请求时如何确定资源是否已经缓存,如何进行缓存?解惑的具体流程:
每次请求资源都会优先查询浏览器是否存在缓存,存在则查看缓存标识信息;每次从服务器请求到资源后都会将资源建立缓存,所以浏览器的缓存机制是关键。
缓存分类
1.强缓存
不向服务器发送请求,直接读取缓存资源,打开F12控制台NetWork可以查看请求资源对于的信息status code:200 (from memory cache)
,强缓存可以通过Expires和Cache-Control
进行实现。
Expires
缓存过期时间,字段信息来源于服务器的响应头,Expires=max-age+请求时间
,服务器响应告诉浏览器在Expires过期之前不需要请求服务器,直接请求缓存资源。
Cache-Control
HTTP/1.1中,Cache-Control是最重要的规则,用于控制网页缓存,设置Cache-Control:max-age=300
代表资源五分钟内同样的资源请求直接命中缓存资源,不需要请求服务器,属于命中强缓存,Cache-Control存在与请求头和响应头,并且可以组合使用指令,具有一下指令规则:
指令 | 作用说明 |
---|---|
public | 表示资源响应过程中可以被客户端和代理服务器缓存 |
private | 资源响应式仅客户端浏览器可以缓存 |
max-age=30 | 资源缓存时间30毫秒(过期需要重新请求) |
s-maxage=30 | 仅在代理服务器中生效(优先级大于max-age) |
no-store | 不缓存任何响应资源 |
no-cache | 资源可被缓存但需要同服务器上一致 |
min-fresh=30 | 30毫秒内若资源过期则请求新资源(容忍最小新鲜度) |
max-stale=30 | 30毫秒内若资源过期则同样适用缓存(容忍最大过期时间) |
- public,资源响应过程中经过的所有节点都可以缓存资源。很多时候资源会经过很多代理服务器(proxy),如果设置public值,请求资源时proxy服务器上的资源未失效则会直接返回给客户端;
- private,资源内容仅客户端可以缓存,Cache-Control的默认值,中间proxy服务器不会缓存,仅作为转发功能;
- no-cache,通过协商缓存来验证是否使用本地缓存资源;
- max-age,表示缓存资源失效时间;
- s-maxage,仅在代理服务器中生效,表示资源失效时间;
- max-stale=30,容忍的最大过期时间,表示客户端愿意接收一个30秒内被修改的过期文件;
- min-fresh=30,容忍的最小新鲜度,表示客户端不接收30秒内被修改的过期文件;
Cache-Control优先级高于Expires,Expires是远古时代的产物,现在常用于兼容写法,强缓存依赖于时间,而且精度也只能是毫秒级。如果服务器和客户端时间不一致则会导致缓存失效的问题。
2.协商缓存
当强缓存失效后就进行协商缓存,浏览器向服务器发送携带缓存标识(Etag和last-modified)的网络请求时,服务器会根据缓存标识处理,如果协商缓存生效则存在两个场景,304和NotModified两种情况;协商失败则返回200状态码和新请求的资源。
Last-Modified和If-Modified-Since
第一次请求支援时,服务器返回资源的同时,响应头中添加Last-Modified属性,表示服务器最后修改的时间,浏览器对资源文件进行缓存和响应头进行保存。下次请求时,浏览器检测到缓存中存在Last-Modified属性,于是在请求头中添加If-Modified-Since属性,这个属性值就是Last-Modified,服务器拿到If-Modified-Since进行比对,转换为时间戳,如果小于最后修改时间,则说明文件存在更新,返回200状态码和新的资源;如果没有更新则返回304和空的响应体,浏览器则直接从缓存读取。
Last-Modified存在如下弊端:
- 如果本地打开缓存文件即使没有修改也会造成Last-Modified变动,服务器匹对不上则导致返回相同的资源;
- 时间精度到秒,无法感知短时间内被修改的文件;
ETag和If-None-Match
Etag是服务器为当前资源建立唯一标识符,资源发生变动则Etag将会重新生成。浏览器请求资源时,服务器返回的响应头中存在Etag属性,下一次浏览器再次发起请求则会在请求头中添加If-None-Match属性且值为Etag,服务器检测到Etag并用于检测是否发生变化,如果发生变化则返回200和新的资源,否则返回返回304通知浏览器直接使用缓存的资源文件。
Last-Modified和Etag相比较不难发现,Etag在精度上优于Last-Modified,但在性能上Etag逊色于Last-Modified,若两者同时存在则优先考虑Etag。
缓存机制
强制缓存优先于协商缓存进行,协商缓存由服务器决定是否使用缓存,协商失败则请求新的资源文件,协商成功则返回304通知客户端使用本地缓存资源。
未设置缓存
如果什么缓存都没设置则浏览器会采用一个启发式的算法,通常取响应头中的 Date 减去 Last-Modified 值的 10% 作为缓存时间。
设置场景
- 频繁变动资源,使用Cache-Control:no-cache,每次请求都将进行协商缓存;
- 不常变化资源,
Cache-Control: max-age=31536000
设置一个超长的缓存时间,当请求相同URL被强缓存命中,文件名处添加打包后的hash值,解决资源变动而浏览器不请求的问题;
寄语
一篇肝了好久的webpack,篇幅很长再加上个人理解可能会有瑕疵,希望大牛别喷,给出的详细webpack.config.js文件我也已经测试过了,我写了很详细的注释,希望能帮到大家!但是如果转载的话希望大家也能注明一下出处!
支持
个人开发了一个资源网址导航网站,很多资源分享,vue项目第一次进会慢一些些,但是过后就很快了,涵盖了生活的方方面面,认真逛逛绝对会有收获,无广告且有软件分享。希望大家支持一下!n.huasenjio.top,如果进不出意外的话我会把这个开源给大家!大家的访问也许对我就是一种鼓励了,谢谢大家!