前端缓存相关

前沿:一直想梳理一下关于缓存相关的几个问题,比如http中控制缓存的几个属性和与缓存相关的http状态码,以及强缓存协商缓存之类以及cookie、session、webStorage以及离线应用缓存等等等。总是云里雾里没有搞得很清楚,今天就来好好的梳理一下。

前端缓存

首先和缓存相关的知识点图谱如图所示

在这里插入图片描述
前端缓存主要分为http缓存和浏览器缓存。其中http缓存是http请求传输时用到的缓存,主要是在服务器代码上设置;而浏览器缓存主要是前端开发在前端js上进行设置。

1 HTTP缓存

1.1 使用缓存的特点

  1. 减少数据的冗余传输
  2. 节省网络费用,缓解网络瓶颈问题
  3. 降低距离延迟
  4. 降低对原始服务器的要求,服务器可以更快响应

1.2 浏览器请求资源的过程

第一次请求
  1. 本地无缓存数据
  2. 向服务器发送请求
  3. 从服务器获取资源并协商缓存(是否缓存,获取资源的Expires,Catch-Control,Etag,Last-Modefied等信息)
  4. 最后呈现页面
    在这里插入图片描述
第二次请求
  1. 先获取资源的header信息,查看是否命中强缓存(根据Cache-Control和Expires判断。其中Cache-Control优先级比Expires高。),若命中则直接从缓存中获取资源,包括缓存header信息,本次请求不会与服务器通信
  2. 如果没有命中强缓存,浏览器会发送请求到服务端,请求头上会携带上次请求资源的响应缓存信息(Last-Modified/If-Modefied-Since和Etag/If-none-Match),服务器根据header信息判断是否命中协商缓存,若命中,返回新的响应头信息,不返回资源,浏览器直接从缓存中读取,否则,返回更新后的资源信息。
1.3 缓存位置

缓存的位置大致分为以下三类: Service worker,Memory cache,Disk cache,优先级按照该顺序,从前向后找,找到返回找不到向服务器请求资源

service worker

用户自定义缓存哪些资源到硬盘上,什么情况下使用缓存。
清空缓存的情况分两种:手动调用api;容量超过限制被浏览器清空
这种方式缓存资源的查看方式 开发者工具-Application-Cache Storage
当资源请求被发起的时候,浏览器首先从service worker中查找资源,如果缓存未命中,一般情况下会使用fetch继续获取资源,这时候浏览器就会去memory cache或者disk cache中进行进一步查找缓存的工作,注意经过fetch方法获取的资源都会显示from service worker,不管实际是从memory cache还是disk cache中还是从网络中

memory cache

内存中的缓存,几乎所有的网络请求资源都会被浏览器自动加入到memory cache中,被短期存储,关闭浏览器窗口后失效。
如果头部设置了no-store则不会进入memory cache

disk cache

硬盘上的缓存,持久存储。绝大多数换缓存都来自于disk cache

如何判断资源从哪里来

chrome的network中的size
(1)资源的大小,多少k:网络请求
(2)from memory disk
(3)from disk cache
(4)from Service worker

1.4强缓存

强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程
①不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求(跟第一次发起请求一致)
在这里插入图片描述
②存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果
在这里插入图片描述
③存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存
在这里插入图片描述

与强缓存相关的字段----Expires/Cache-Control

Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。

到了HTTP/1.1,Expire已经被Cache-Control替代,原因在于Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,那么如果客户端与服务端的时间因为某些原因(例如时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓存则会直接失效,这样的话强制缓存的存在则毫无意义
在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存,主要取值为:
public:所有内容都将被缓存(客户端和代理服务器都可缓存)
private:所有内容只有客户端可以缓存,Cache-Control的默认取值
no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效

在这里插入图片描述
由上面的例子我们可以知道: ①HTTP响应报文中expires的时间值,是一个绝对值 ②HTTP响应报文中Cache-Control为max-age=600,是相对值由于Cache-Control的优先级比expires高,那么直接根据Cache-Control的值进行缓存,意思就是说在600秒内再次发起该请求,则会直接使用缓存结果,强制缓存生效。注:在无法确定客户端的时间是否与服务端的时间同步的情况下,Cache-Control相比于expires是更好的选择,所以同时存在时,只有Cache-Control生效。

了解强制缓存的过程后,我们来看一下缓存都存在了哪里。
在这里插入图片描述
返回状态码为200ok(from disk cache)等表示命中强缓存,from**表示缓存存放的位置,分别有from memory cache和from disk cache。
(1)from memory cache表示使用内中的缓存,内存缓存速度快但是有时间限制
(2)from disk cache表示使用硬盘中的缓存,硬盘缓存是直接将缓存写入硬盘之中,读取缓存需要对缓存存放硬盘文件进行I/O操作,然后重新解析该缓存内容,比内存缓存慢

在浏览器中,浏览器会在js和图片 等文件解析执行后直接存入内存缓存中,那么当刷新页面时只需要直接从内存缓存中读取(from memory cache)。而css文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘中读取缓存(from disk cache)

浏览器读取缓存的顺序为 memory–>disk–>服务器请求。

比如首次打开一个网站访问页面:
在这里插入图片描述

关闭页面重新打开
在这里插入图片描述
刷新页面
在这里插入图片描述

1.5 协商缓存

协商缓存就是强缓存失效以后,浏览器携带缓存标识向服务器发起请求,由服务器决定标识是否继续使用缓存。

①协商缓存生效,继续使用缓存,返回304 Not modified

②协商缓存失效,返回200和请求结果结果
在这里插入图片描述

与协商缓存相关的字段----Last-Modified / If-Modified-Since和Etag / If-None-Match,

Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间
If-Modified-Since则是客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件

Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)
If-None-Match是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200

注:Etag / If-None-Match优先级高于Last-Modified / If-Modified-Since,同时存在则只有Etag / If-None-Match生效。

为什么有了Last-Modified的还需要Etag?

Etag 主要为了解决 Last-Modified 无法解决的一些问题:

1、一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
2、某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒)
3、某些服务器不能精确的得到文件的最后修改时间;

1.6 浏览器行为

  1. 打开网页,地址栏输入地址,检查是否命中强缓存,若无,再与服务器端交互检查协商缓存或返回数据
  2. 普通刷新F5:这种情况下,实际上是浏览器将cache-control的max-age直接设置成0,让缓存立即过期,走协商缓存的路线
  3. 强制刷新F5+ctrl:浏览器不使用缓存,因此发送的请求头部均带有Cache-control:no-cache,服务器直接返回200和最新内容

整个的缓存过程如图所示:
在这里插入图片描述

2 浏览器缓存

2.1 cookie

cookie和session都是为了弥补http协议的无状态,对于server端来说,无法知道两次http请求是否来自与同一个客户,利用cookie和session可让用户只登陆一次就知道是否需要重新登录

  1. cookie:存储在客户端,大小4k为上限,每次请求的时候需要携带cookie。客户端第一次正常访问服务器,服务器在response headers中返回与用户信息相关的cookie,客户端收到后把cookie保存在本地,下次再发请求时会在request headers中带上这个cookie,服务器收到这个cookie就知道用户状态了
  2. session:存放在服务器端,会话级别的存储,没有大小限制,比cookie安全。客户端第一次正常访问服务器,服务器生成一个sessionid来标识用户并保存用户信息(服务器有一个专门的地方来保存所有用户的sessionId),在response headers中作为cookie的一个值返回,客户端收到后把cookie保存在本地,下次再发请求时会在request headers中带上这个sessionId,服务器通过查找这个sessionId就知道用户状态了,并更新sessionId的最后访问时间

cookie 和 session 区别

(1)保存状态不同:
Cookie保存在浏览器端,服务端可以知道其中的信息。
Session保存在服务器端,客户端不知道其中的信息。

(2)使用方式不同:
Cookie机制:

如果不在浏览器中设置过期时间,Cookie被保存在内存中,生命周期随浏览器的关闭而结束,这种Cookie简称会话Cookie。
如果在浏览器中设置了Cookie的过期时间,Cookie被保存在硬盘中,关闭浏览器后,Cookie数据仍然存在,直到过期时间结束才消失。
Cookie是服务器发给客户端的特殊信息,Cookie是以文本的方式保存在客户端,每次请求时都带上它。

Session机制:

当服务器收到请求需要创建Session对象时,首先会检查客户端请求中是否包含sessionid。
如果有sessionid,服务器将根据该id返回对应Session对象。
如果客户端请求中没有sessionid,服务器会创建新的Session对象,并把sessionid在本次响应中返回给客户端。
通常使用Cookie方式存储sessionid到客户端,在交互中浏览器按照规则将sessionid发送给服务器。
如果用户禁用Cookie,则要使用URL重写,可以通过response.encodeURL(url) 进行实现。API对encodeURL的解释为:
当浏览器支持Cookie时,url不做任何处理。
当浏览器不支持Cookie的时候,将会重写url将SessionID拼接到访问地址后。

(3)存储的大小不同:
Cookie:单个Cookie保存的数据不能超过4kb.
Session大小没有限制。

(4)安全性不同:
针对Cookie所存在的攻击:Cookie欺骗,Cookie截获。
Session的安全性大于Cookie。

(5)应用场景不同:
Cookie:
判断用户是否登陆过网站,以便下次登录时能够实现自动登录(或者记住密码)。如果我们删除Cookie,则每次登录必须重新填写登录的相关信息。

  • 保存上次登录的时间等信息。
  • 保存上次查看的页面。
  • 浏览计数。

Session:Session用于保存每个用户的专用信息,变量的值保存在服务器端,通过SessionID来区分不同的客户。

  • 网上商城中的购物车。
  • 保存用户登录信息。
  • 将某些数据放入session中,供同一用户的不同页面使用。
2.2 localStorage

在HTML5中,新加入了一个localStorage特性,这个特性主要是用来作为本地存储来使用的,解决了cookie存储空间不足的问题(cookie中每条cookie的存储空间为4k),localStorage中一般浏览器支持的是5M大小。
webStorage的使用:
①检测浏览器是否支持。if(window.sessionStorage){ operationA }
②储存值。setItem(key, value)
例:localStorage.setItem(“site”,”mysite.com”);
③读取值,getItem(key)
例:localStorage.getItem(“site”);
④删除值,removeItem(key)
例:sessionStroage(“site”);
⑤清空本地存储,clear(),清除本地的键值对
例:localStorage.clear();
⑥遍历操作,利用key(i)和length
var store=window.localStorage;
for(var i=0,len=store.length;i<len;i++){
console.log(store.key(i)+”:”+store.getItem(store.key(i)));
}
⑦storage事件,当键值改变或者clear的时候,就可以触发storage事件

2.3 sessionStroage

sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储

补充cookie和webStorage的区别:
共同点:都是保存在浏览器端,并且是同源的
①cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递cookie数据还有路径(path)的概念,可以限制。cookie只属于某个路径下
②存储大小限制也不同,cookie数据不能超过4K,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如回话标识。webStorage虽然也有存储大小的限制,但是比cookie大得多,可以达到5M或更大
③数据的有效期不同,sessionStorage:仅在当前的浏览器窗口关闭有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前一直有效,即使窗口和浏览器关闭
④作用域不同sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;localStorage:在所有同源窗口都是共享的;cookie:也是在所有同源窗口中共享的

2.4 本地存储大容量

WebSql和IndexDB主要用在前端有大容量存储需求的页面上,例如,在线编辑浏览器或者网页邮箱

在这里插入图片描述

2.5 Application cache

H5的ApplicationCacheAPI提供离线存储offline storage功能,核心是:在用户没有与因特网连接时,依然能够访问站点或应用(自定义一些要缓存的图片、flash、css、JavaScript、HTML等),在用户与因特网连接时,自动更新缓存功能。
由于浏览器支持不同,所以在使用之前进行测试,window.applicationCache
离线技术主要包含两部分①manifest缓存清单(包含一些需要缓存的资源清单) ②JavaScript接口(提供了用于更新缓存文件的方法以及对缓存文件的操作)

manifest文件
一个文本文件,MIME类型是text/cache-manifest,每个站点都有5MB的空间来存储。
第一行是CACHE MANIFEST
然后就是文件的路径和注释,注释以#开头,有CACHE和NETWORK和FALLBACK等。

在线状态检测
1.navigator.onLine
navigator.onLine 属性表示当前是否在线。如果为 true, 表示在线;如果为 false, 表示离线。当网络状态发生变化时,navigator.onLine 的值也随之变化。开发者可以通过读取它的值获取网络状态。

2.online/offline 事件
当开发离线应用时,通过 navigator.onLine 获取网络状态通常是不够的。开发者还需要在网络状态发生变化时立刻得到通知,因此 HTML5 还提供了 online/offline 事件。当在线 / 离线状态切换时,online/offline 事件将触发在 body 元素上,并且沿着 document.body、document 和 window 的顺序冒泡。因此,开发者可以通过监听它们的 online/offline 事件来获悉网络状态。

参考文献

https://www.jianshu.com/p/256d0873c398
https://www.jianshu.com/p/33dddbee9204
https://www.haorooms.com/post/cache_huancunliyong
https://www.cnblogs.com/belove8013/p/8134067.html
https://blog.csdn.net/weixin_44239490/article/details/89520808

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值