8.5浏览器缓存
参考
https://www.jianshu.com/p/54cc04190252
https://www.cnblogs.com/chengxs/p/10396066.html
https://blog.csdn.net/xiamiflying/article/details/88667876
应用场景还没总结
1. 如果在一个有cookie的页面,再从这个页面的链接跳转,那么在跳转的页面还能拿到cookie和session,但是如果是新开窗口就拿不到session了,因为在同一个页面跳转也属于上一个页面的会话,新开网页就是新的会话了
2. 浏览器缓存
1. 浏览器是根据http报文的缓存标识进行的
浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存
强缓存如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器
当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,
如果协商缓存命中,服务器会将这个请求返回,但是不会返回这个资源的数据,
而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器就又会从自己的缓存中去加载这个资源。
强缓存与协商缓存的共同点是:如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据;
区别是:强缓存不发请求到服务器,协商缓存会发请求到服务器。
当协商缓存也没有命中的时候,浏览器直接从服务器加载资源数据。
2. 请求报文和响应报文中都有的请求头和响应头
1. Cache-Control、Connection、Date、Pragma、Transfer-Encoding、Upgrade
2. Allow、Content-Base、Content-Encoding、Content-Language、Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、Etag、Expires、Last-Modified、extension-header
3. 缓存过程:浏览器发起请求-----服务器响应请求
1. 浏览器第一次拿到请求结果------所有response header一起缓存下来
根据响应报文的响应头里面的缓存标识来决定是不是要缓存结果,是的话就存入浏览器缓存中
2. 所以浏览器每次发请求的时候会现在浏览器缓存中查找同一个请求的结果和标识,每次拿到结果也会将结果和标识放在缓存中
4. 然后根据是否需要向服务器重新发起http请求将缓存分为强缓存和协商缓存
1. 强缓存
1. 强缓存发请求之前根据缓存规则response header会先去浏览器缓存查找该请求结果
1. 如果不存在结果和缓存标识就发起请求
2. 存在但是失效就使用协商缓存
3. 存在并且没有失效就直接返回结果
2. 缓存规则在服务器返回的响应头中,控制字段是expires和cache-control
1. expires是http1.0的字段,指的是服务器返回该请求的结果缓存的到期时间,也就是说再一次发请求的时候,时间还没超过这个值就直接用缓存结果
控制缓存的原理是用客服端时间和服务端返回的时间做对比,有一方有误差就直接无效所以http1.1用cache-control
2. cache-control是一个相对值,并且优先级高于expires,有多个指令
例如
-
-
private 响应只能被客户端缓存
-
no-store 不缓存
-
no-cache 资源缓存立即失效,下次会发起请求验证资源
-
https://upload-images.jianshu.io/upload_images/3174701-8ff981603cdfded0?imageMogr2/auto-orient/strip|imageView2/2/w/562/format/webp
https://upload-images.jianshu.io/upload_images/3174701-3fa81f5e9efac5af?imageMogr2/auto-orient/strip|imageView2/2/format/webp
应用:
- 强缓存是前端性能优化最有力的工具,没有之一,对于有大量静态资源的网页,一定要利用强缓存,提高响应速度。通常的做法是,为这些静态资源全部配置一个超时时间超长的Expires或Cache-Control,这样用户在访问网页时,只会在第一次加载时从服务器请求静态资源,其它时候只要缓存没有失效并且用户没有强制刷新的条件下都会从自己的缓存中加载,-------问题是发布新资源会更新不了----解决办法http://www.zhihu.com/question/20790576
2. 协商缓存:强缓存判断是否缓存是根据结果字段是根据时间,但是不知道服务器内容是否更新,所以就要用到协商缓存
1. 当强缓存失效之后,浏览器携带缓存标识发起请求,由服务器根据标识决定是否使用缓存
1. 协商缓存生效,返回304和not modified
2. 协商缓存失效,返回200和结果
2. 协商缓存通过响应头中的last-modified和if-modified-since设置
1. last-modified指的是这个请求资源在服务器的最后修改时间,浏览器收到后就缓存结果和指令
2. 然后再发请求的时候再缓存中找到了这个指令就添加 if-modified-since字段=last-modified的值,
3. 服务器收到这个请求根据if-modified-since的值与服务器这个资源的最后修改时间做对比,值一样就返回304和空响应主体,浏览器就从缓存读取结果,如果值更小就说明有更新,返回200和新的结果
3. 但是last-modified的值如果再本地打开了缓存文件会改变所有这个会造成服务器发送同样的资源
3. etag 和 if-none-match
1. etag是当前这个请求资源的唯一标识,只要资源有变化就会重新生成
2. 浏览器再发请求的时候会吧etag放到请求头的If-None-Match中,服务器只需要比较这个etag和服务器这个资源的etag就知道资源是否改变了
3. 没改变就是304和直接使用缓存,改变就是返回200和新结果
4. 总结缓存机制:强缓存优先协商缓存(也就是有expries和cache-control),强缓存失效就进行协商缓存(last-modifide/if-modified-since和etag/if-none-match),但是这个是由服务器决定,如果协商缓存失效这个请求的缓存就没有,就直接返回200 和结果标识,然后又存入缓存,--------协商缓存生效就返回304继续使用缓存中的资源
优先级:Cache-Control>Expires>Etag>Last-modify
https://upload-images.jianshu.io/upload_images/3174701-9d9e8b52a18ed35a?imageMogr2/auto-orient/strip|imageView2/2/w/519/format/webp
3.
-
service worker:必须使用https,因为要拦截请求,fetch
-
memory cache:内存缓存,包含下载的样式脚本图片等,缓存持续性很短,关闭tab内存的缓存就释放了
-
内存中有一个preloader可以一边解析css js文件一边请求下一个资源
-
-
disk cache 硬盘缓存:速度慢一点
-
Push Cache(推送缓存)是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂
-
应用场景
-
频繁变动的资源:用强缓存的cache-control:no-cache,每次都发送请求,再配etag或者last-modified验证资源是否没变,这样可以减少响应数据的大小、
-
常变化的资源:Cache-Control: max-age=31536000一年,而为了解决更新的问题,就需要在文件名(或者路径)中添加 hash, 版本号等动态字符,之后更改动态字符,从而达到更改引用 URL 的目的,让之前的强制缓存失效 (其实并未立即失效,只是不再使用了而已)。 在线提供的类库 (如
jquery-3.3.1.min.js
,lodash.min.js
等) 均采用这个模式 -
用户行为的影响
-
输入网址查找disk cache有就直接使用,没有就发起请求
-
普通刷新f5:tab没有关闭,左右memory cache可以用,所以先在内存中再去disk cache中查找
-
强制刷新:ctrl+f5,不使用缓存,服务器返还200和结果
-
-
-
-
如果资源已经被浏览器缓存下来,在缓存失效之前,再次请求时,默认会先检查是否命中强缓存,如果强缓存命中则直接读取缓存,如果强缓存没有命中则发请求到服务器检查是否命中协商缓存,如果协商缓存命中,则告诉浏览器还是可以从缓存读取,否则才从服务器返回最新的资源。这是默认的处理方式,这个方式可能被浏览器的行为改变:
1、当ctrl+f5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存;
2、当f5刷新网页时,跳过强缓存,但是会检查协商缓存