关于浏览器缓存的利用
如果很好的利用缓存能够很好的对网页速度进行优化,能够缩短请求资源的时间,对于已缓存的文件可以直接访问缓存,能够减少带宽。
当我们请求数据时,可以利用缓存直接访问缓存的内容不发起请求,或者是发起请求但是后端存储的资源并未发生改变,就不再将数据回传,能够减少数据响应的时间。
缓存的位置
缓存按位置区分可以分为四种,Service Worker,Memory Cache,Disk Cache,Push Cache,当依次查找这些位置都没有找到时,才会去请求网络。
1.Service Worker
Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用 Service Worker的话,传输协议必须为 HTTPS。因为 Service Worker 中涉及到请求拦截,所以必须使用 HTTPS 协议来保障安全。Service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。
2.Memory Cache
Memory Cache是内存中的缓存,主要包含的是当前中页面中已经获取到的资源,例如页面上已经下载的样式、脚本、图片等,当我们访问过页面再次刷新就会发现里面很多内容都会访问缓存,即状态码为304,读取内存速度较快,但是缓存持续性很短并且,关闭当前的Tab 页面,内存中的缓存也就被释放了。
需要注意的事情是,内存的缓存与Cache-Contro的值无关,去匹配资源的时候不仅要对url做匹配,还可能对Content-Type,CORS等其他特征进行匹配。
3. Disk Cache
Disk Cache 是存储在硬盘中的缓存,读取速度比Memory Cache慢,但是什么都能存储到磁盘中,比之 Memory Cache 能缓存的数据更多时效性更长。
在所有浏览器缓存中,Disk Cache 覆盖面基本是最大的。它会根据 HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。并且即使在跨站点的情况下,相同地址的资源一旦被硬盘缓存下来,就不会再次去请求数据。绝大部分的缓存都来自 Disk Cache。
4. Push Cache
这个一般很少使用,一般是在前面的三种都没找到他才会被使用。
缓存的方式
强缓存
可以通过对HTTP Header 中的Expires和Cache-Control来实现
1.设置Expires
设置Expires=max-age + 请求时间,可以在设置的过期时间前访问缓存中的数据。但是如果更改了本地时间,可能就会影响缓存的时效。
例如:
Expires: Wed, 01 Oct 2021 00:21:00 GMT表示资源会在 Wed, 01 Oct 2021 00:21:00 GMT 后过期,需要再次请求获取数据。
2.设置Cache-Control
指令 | 作用 |
---|---|
public | 所有内容都将被缓存,客户端和代理服务器都可缓存 ,可被任何中间节点缓存。 |
private | 所有内容只有客户端可以缓存,代理服务器只能转发不能缓存。 |
no-cache | 浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致。如果不一致则发起请求,一致则会访问缓存 |
no-store | 所有内容都不会缓存,即每次都会请求最新的内容 |
max-age | max-age=xx,表示缓存内容在xx秒后消失。 |
s-maxage | 同max-age作用一样,只在代理服务器中生效。s-maxage的优先级高于max-age。如果存在s-maxage,则会覆盖掉max-age。 |
max-stale | 能容忍的最大过期时间,max-stale=30,30秒内即使缓存过期也会使用缓存 |
min-fresh | 能够容忍的最小新鲜度。min-fresh标示了客户端不愿意接受新鲜度不多于当前的age加上min-fresh设定的时间之和的响应。例如min-fresh=30,希望在30s内获取最新的响应。 |
Expires和Cache-Control相比较
1.Cache-Control优先级高于Expires。
2.不支持HTTP1.1的情况下使用Expires,不能使用Cache-Control。
3.对于频繁变动的资源使用Cache-Control: no-cache是比较好的选择,既能够在服务器端数据有所更新时发送请求获取最新的内容,也能在服务器端资源未更新的情况下访问缓存。
4.对于不常变化的资源可以设置Cache-Control: max-age=xx,在资源更新的时候我们可以通过更改资源的名称以及版本号来使其访问最新的内容。
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。
协商缓存可以通过设置HTTP Header中的Last-Modified 和 ETag 来实现。
1.Last-Modified和If-Modified-Since
在浏览器第一次请求URL时,服务器返回资源的同时,在response header中添加 Last-Modified的header,值是这个资源在服务器上的最后修改时间,浏览器接收后缓存文件和header;
客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过
如果服务器端的资源没有变化,则自动返回 304状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则返回资源,返回和第一次请求时类似。从而实现服务器端资源更新时使用最新资源,未更新时使用缓存。
2.ETag和If-None-Match
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。如果服务器发现ETag匹配不上,将新的资源以新的ETag发给客户端;如果ETag是一致的,则直接返回304。
两者相比较
1.精确度上,Etag要优于Last-Modified。
2.性能上,Etag要比Last-Modified略差,因为Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
3.优先级上,服务器校验优先考虑Etag
缓存方式优先级
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match)。
优先级为:Cache-Control>Expires>Etag>Last-Modified
用户操作会对缓存产生的影响
打开页面,地址栏输入地址: 查找 disk cache 中是否有匹配。如有则使用;如没有则发送网络请求。
普通刷新 (F5):因为 TAB 并没有关闭,因此 memory cache 是可用的,会被优先使用(如果匹配的话)。其次才是 disk cache。
强制刷新 (Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache,服务器直接返回 200 和最新内容。