关于http缓存:ServiceWorker-缓存与-HTTP-缓存

尽管 ServiceWorker 和 PWA 正在成为古代 Web 应用程序的规范,但浏览器资源缓存变得比以往任何时候都简单。 本文涵盖了浏览器缓存的重点内容,具体包含: ServiceWorker 缓存与 HTTP 缓存的优先级?支流浏览器实现的 MemoryCache 和 DiskCache 在哪一层?MemoryCache、DiskCache、ServiceWorker 缓存哪个速度更快?缓存流程概述咱们先来看规范定义的资源申请遵循的程序: ServiceWorker 缓存:ServiceWorker 查看资源是否存在其缓存中,并依据其编程的缓存策略决定是否返回资源。这个操作不会主动产生,须要在注册的 ServiceWorker 中定义 fetch 事件去拦挡并解决网络申请,这样能力命中 ServiceWorker 缓存而不是网络或者 HTTP 缓存。HTTP 缓存:这里就是咱们经常说的「强缓存」和「协商缓存」,如果 HTTP 缓存未过期的话,浏览器就会应用 HTTP 缓存的资源。服务器端:如果 ServiceWorker 缓存或者 HTTP 缓存中未找到任何资源,则浏览器会向网络申请资源。这里就会波及到 CDN 服务或者源服务的工作了。这是规范定义的资源申请流程,然而有谋求的浏览器还会在 ServiceWorker 下面加一层 「内存缓存层」 ,以 Chrome 为例,咱们申请一个资源,除去网络,会有三种浏览器缓存返回: 那么 MemoryCache 和 DiskCache 与 ServiceWorker Cache 的优先级是怎么样的呢? 上面咱们讲讲三者的区别。 MemoryCache、DiskCache 在缓存流程的哪一层?咱们以 Chrome 为例,MemoryCache 作为第一公民,位于 ServiceWorker 之上。 也就是命中了 MemoryCache,就不会触发 ServiceWorker 的 fetch 事件。 而 DiskCache 则位于原来的 HTTP 缓存层: ...

April 21, 2022 · 2 min · jiezi

关于http缓存:爪哇学习笔记HTTP缓存

什么是缓存?缓存是一种保留资源正本并在下次申请时间接应用该正本的技术。当 web 缓存发现申请的资源曾经被存储,它会拦挡申请,返回该资源的拷贝,而不会去源服务器从新下载。缓存的作用缓解服务器端压力,晋升性能(获取资源的耗时更短了)。缓存分类公有缓存公有缓存只能用于独自用户。浏览器缓存共享(共有)缓存共享缓存能够被多个用户应用。代理缓存网关缓存CDN反向代理缓存缓存命中和缓存未命中能够用已有的正本为某些达到缓存的申请提供服务,这被称为缓存命中(cache hit)。其余一些达到缓存的申请可能会因为没有正本可用,而被转发给原始服务器,这被称为缓存未命中(cache miss)。 再验证原始服务器的内容可能会发生变化,缓存要不断对其进行检测,看看它们保留的正本是否仍是服务器上最新的正本。这些“新鲜度检测”被称为HTTP再验证。 缓存对缓存的正本进行再验证时,会向原始服务器发送一个小的再验证申请。如果内容没有变动,服务器会一个小的304 Not Modified进行响应。只有缓存晓得正本依然无效,就会再次将正本标识为临时陈腐的,并将正本提供给客户端。这被称作再验证命中或迟缓命中。因为要与服务器进行核查,所以这种形式比缓存命中要慢,然而它没有从服务器获取对象数据,所以比缓存未命中要快一些。 最罕用的再验证工具If-Modified-Since首部再验证命中如果服务器对象未被批改,服务器会向客户端发送一个小的HTTP 304 Not Modified响应。再验证未命中。如果服务器对象已与缓存正本不同,服务器向客户端发送一条一般的、带有残缺内容的HTTP 200 OK响应。对象被删除如果服务器对象曾经被删除了,服务器就会回送一个404 Not Found响应,缓存也会将其正本删除。辨别命中和未命中的状况HTTP没有为用户提供一种伎俩来辨别响应是缓存命中的,还是拜访原始服务器失去的。在这两种状况下,响应码都是200 OK,阐明响应有主题局部。 客户端有一种办法能够判断响应是否来自缓存,就是应用Date首部(将Date首部的值与以后工夫进行比照)。客户端也能够通过Age首部来检测缓存的响应,通过这个首部能够分辨出这条响应的使用期。 缓存的解决步骤对一条HTTP GET报文的根本缓存处理过程包含7个步骤: 接管——缓存从网络中读取到达的申请报文。解析——缓存对报文进行解析,提取出URL和各种首部。查问——缓存查看是否有本地正本可用,如果没有,就获取一份正本并将其保留在本地新鲜度检测——缓存查看已缓存的正本是否够陈腐,如果不是,就询问服务器是否有任何更新创立响应——缓存会用新的首部和已缓存的主体来构建一条响应报文发送——缓存通过网络将响应发回给客户端日志——写日志记录放弃正本的陈腐HTTP有一些简略的机制能够在不要求服务器记住有哪些缓存领有其正本的状况下,放弃已缓存数据与服务器数据之间充沛统一。HTTP将这些简略的机制称为文档过期和服务器再验证。 文档过期通过非凡的HTTP Cache-Control首部和Expires首部,HTTP让原始服务器向每个文档附加了一个“过期日期”。 在缓存文档过期之前,缓存能够以任意频率应用这些正本,而无需与服务器分割——当然,除非客户端申请中蕴含有阻止提供已缓存或未验证资源的首部。但一旦已缓存文档过期,缓存就必须与服务器进行核查,询问文档是否被批改过,如果被批改过,就要获取一份陈腐的正本。 过期日期和使用期服务器用HTTP/1.0+的Expires首部或HTTP/1.1的Cache-Control: max-age响应首部来指定过期日期,同时还会带有响应主体。 Cache-Control: max-agemax-age值定义了文档的最大使用期——从第一次生成文档到文档不再陈腐、无奈应用为止,最大的非法生存工夫(以秒为单位)Expires指定一个相对日期。如果过期日曾经过了,就阐明文档不再陈腐了服务器再验证仅仅是缓存文档过期了并不意味着它和原始服务器上目前处于沉闷状态的文档有理论的区别,这只意味着到了要进行核查的工夫了。这种状况被称为“服务器再验证”,阐明缓存须要询问原始服务器是否产生了变动。 如果产生了变动,缓存会获取一份新的文档正本,并将其存储在旧文档的地位上,而后将文档发送给客户端。如果没有发生变化,缓存只须要获取新的首部,包含一个新的过期日期,并对缓存中的首部进行更新就好了。用条件办法进行再验证HTTP容许缓存向服务器发送一个“条件GET”,申请服务器只有在文档与缓存中现有正本不同时,才会回送对象主体。通过这种形式,将新鲜度检测和对象获取联合成了单个条件GET。向GET申请报文中增加一些非凡的条件首部,就能够发动条件GET。只有条件为真时,Web服务器才会返回对象。 HTTP定义了5个条件首部。对缓存再验证来说最有用的2个首部是If-Modified-Since和If-None-Match。 If-Modified-Since:<date>如果从指定日期之后文档被批改了,就执行申请的办法。能够与Last-Modified服务器响应首部配合应用If-Modified-Since: <cached last-modified date>,只有在内容被批改后与已缓存版本有所不同的时候才去获取内容If-None-Match:<tags>服务器能够为文档提供非凡的标签(ETag),而不是将其与最近批改日期相匹配,这些标签就像序列号一样。如果已缓存标签与服务器文档中的标签有所不同,If-None-Match首部就会执行所申请的办法强弱验证器实体标签和最近批改日期都是缓存验证器。 有时候,服务器心愿在对文档进行一些非实质性或不重要的批改时,不要使所有已缓存正本都生效。HTTP/1.1反对弱验证器,如果只是对内容进行了大量批改,就容许服务器申明那是“足够好”的等价体。 只有内容产生了变动,强验证器就会变动。弱验证器容许对一些内容进行批改,但内容的次要含意发生变化时,通常它还是会变动的。 什么时候应该应用实体标签和最近批改日期如果服务器回送了实体标签,HTTP/1.1客户端就必须应用实体标签验证器如果服务器只回送了一个Last Modified值,客户端就能够应用If-Modified-Since验证如果实体标签和最初批改日期都提供了,客户端就应该应用这两种再验证计划,这样HTTP/1.0和HTTP/1.1缓存就都能够正确响应了如果HTTP/1.1缓存或服务器收到的申请既带有If-Modified-Since,又带有实体标签条件首部,那么只有这两个条件同时满足时,能力返回304 Not Modified响应管制缓存的能力no-store与no-cache响应首部Pragma: no-cacheCache-Control: no-storeCache-Contorl: no-cache标识为no-store的响应会禁止缓存对响应进行复制(即不容许将响应主体对象存到缓存中区)。标识为no-cache的响应实际上是能够存储在本地缓存区中的。只是在与原始服务器进行新鲜度再验证之前,缓存不能将其提供给客户端应用。HTTP/1.1中提供Pragma: no-cache首部是为了兼容于HTTP/1.0+。除了与只了解Pragma: no-cache的HTTP/1.0应用程序进行交互时,HTTP/1.1应用程序都应该应用Cache-Contorl: no-cache。 max-age响应首部Cache-Contorl: max-age首部示意的是从服务器将文档传来之时起,能够认为此文档处于陈腐状态的秒数。还有一个s-maxage首部,其行为与max-age相似,但仅实用于共享缓存: Cache-Control: max-age=3600Cache-Control: s-maxage=3600服务器能够申请缓存不要缓存文档,或者将最大使用期设置为零,从而在每次拜访的时候都进行刷新: Cache-Control: max-age=0Cache-Control: s-maxage=0Expires响应首部不举荐应用Expires首部,它指定的是理论的过期日期而不是秒数。 expires: Wed, 09 Feb 2022 05:41:19 GMT有些服务器还会回送一个expires: 0响应首部,试图将文档置于永远过期的状态,但这种语法是非法的,可能给某些软件带来问题。 must-revalidate响应首部能够配置缓存,使其提供一些古老(过期)的对象,以进步性能。如果原始服务器心愿缓存严格遵守过期信息,能够在原始响应中附加一个Cache-Control: must-revalidate首部。 Cache-Control: must-revalidatemax-stale响应首部Cache-Control: max-staleCache-Control: max-stale=<s>缓存能够随便提供过期的文件。如果指定了<s>参数,在这段时间内,文档就不能过期。这条指令放松了缓存的规定。 ...

January 15, 2022 · 1 min · jiezi

关于http缓存:HTTP缓存

什么是HTTP缓存当客户端向服务器发送申请时,先到达浏览器获取缓存数据。 缓存个别从第二次申请开始,且只能缓存get申请响应的资源。 HTTP缓存分为强缓存和协商缓存 强缓存Cache-Control : max-age 设置缓存存在工夫,优先级比Expires高 Expires: 绝对工夫 可能客户端和服务器之间会有误差 协商缓存Cache-Control : no-cache 设置协商缓存 不缓存Cache-Control : no-store 不缓存 pragma 只有一个选项no-cacha,告诉浏览器不实用缓存,并且优先级最高

May 19, 2021 · 1 min · jiezi

http的强缓存和弱协商缓存

概念浏览器缓存主要分为本地缓存(又称强缓存)和弱缓存(又称协商缓存) 强缓存用户发送的请求,直接从客户端缓存中获取资源、不发送到服务器。不会与服务器发生任何的交互行为弱缓存用户发送的请求,发送给服务器,由服务器判断是否从缓存中拿资源1、第一次请求的时候,浏览器无缓存,用户发送请求到服务端,服务端响应请求。此时浏览器端将响应进行缓存。具体大概是,第一次请求到服务端时,服务端会把页面的最后修改时间通过在response-header的last-modified告诉浏览器。浏览器将页面的最后修改时间进行记录。还会生成一个Etag。2、用户第二次在访问的时候,浏览器会判断缓存是否过期, 没有过期,直接从缓存中获取资源进行呈现。没有过期,会有两种缓存机制的方式,如下:1、第一种 是查看是否有Etag,如果有查看响应服务端资源版本的报文头信息Etag是否发生改变(就是查看Etag,如果发送给服务端的某个资源发生变化了,Etag就会响应的发生变化),如果发生改变,向服务器请求的时候,会在request-header中添加if-none-match属性,属性值就是Etag的值,本次请求,发送给服务端之后,服务端将属性值和存的Etag进行对比。如果服务端验证资源的Etag没有改变的时候,将返回304状态,告诉浏览器使用本地缓存。因为资源没有更新。如果Etag有改变的时候,会返回200把新的资源和新的Etag响应给浏览器。2、第二种 是查看是否有last-modified,查看值是多少,它代表当前资源的缓存时间/即页面的最后修改时间,然后看当前资源的request-header中的last-modified-since。这个是告诉服务器当前资源的缓存时间,请求也会把此时间发送给服务端,服务端会将两者进行对比,如果时间一致,证明没有修改,服务器会返回304,告诉浏览器直接从本地缓存中获取资源,如果时间不一致,会返回200新的资源给浏览器。浏览器拿到之后会丢弃掉之前缓存的,把新的资源缓存,然后每一次请求都会用这种方式。3、如果既没有Etag又没有last-modified,就会直接向服务器请求,服务器响应,然后进行缓存协商。最后呈现。你就记住,Etag是结合if-none-match使用的, last-modified是结合last-modified-since使用的,然后搞清楚两者的结合使用关系即可。

October 14, 2019 · 1 min · jiezi

细说HTTP缓存

为什么要使用缓存 ?缓存是可以自动保存为常见文档副本的 HTTP 设备,当 web 请求抵达缓存时。如果本地有已缓存了的副本,就可以从本地存储设备上直接提取这个文档,而不用去服务器中提取。 缓存可以帮助我们: 缓解服务器压力,提高了网站性能加快了网页加载速度,提升了用户的使用体验减少了冗余的数据传输,帮助网络运营减少了流量HTTP 缓存处理流程 第一步:接收请求并解析缓存从网络中读取抵达的请求报文,然后将请求报文解析成片段,将首部的各个部分放入易于操作的数据结构中,这样缓存就更容易处理首部字段并修改它们了 第二步:查找缓存副本缓存获取 URL,查找本地副本。本地副本存储在内存、本地磁盘等地方,缓存会确认本地缓存中是否有这个对象,查找会有以下两种结果: 第一种结果:未找到可用副本到达缓存的请求因为没有查找到可用的副本,会将请求转发给原始服务器去获取资源(缓存未命中),并将该资源缓存在本地 第二种结果:已找到可用副本到达缓存的请求查找到了可用副本,在向客户端提供该文档之前,HTTP 会对此文档进行新鲜度检测。 HTTP 通过缓存将服务器文档的副本保留一段时间,这段时间内(默认一小时或一天)都认为文档是新鲜的,缓存可以在不联系服务器的情况下直接提供向客户提供该文档(缓存命中,200 OK)。 一旦已缓存副本停留的时间过长,超过了文档的新鲜度限值,就会认为该对象不新鲜,这种情况下缓存会向服务器发送一个再验证请求来进行确认,以便查看文档是否发生了变化,再验证可能的结果如下: 再验证命中如果内容没有变化,服务器会向客户端发送一个HTTP 304 Not Modified 的响应,缓存知道副本仍然有效了,就会对该缓存文档新鲜度进行更新,然后将缓存文档返回给客户端。 再验证未命中如果服务器的内容有变化,就从服务器上重新获取该资源,并更新本地的缓存数据(200 OK) 对象被删除如果内容被删除,服务器返回一个404 Not Found,缓存也会将其副本删除掉。 新鲜度检测流程: 浏览器第一次向服务器发起请求:服务端在响应头返回协商缓存的头属性:ETag、Last-Modified; 浏览器第二次向服务器发发起请求:在请求头中带上与 ETag 对应的 If-Not-Match(值为上次请求时返回响应头的 ETag 值)和与 Last-Modified 对应的 If-Modified-Since。 服务器接收到这两个参数后会作比较,看看资源有没有失效或者有更改。如果返回的是 304 状态码,则表示资源没有任何修改,缓存会标记副本为新鲜并把资源返回给客户端,否则服务器会返回200 状态码,直接返回一份新的资源。 第三步:创建响应缓存将副本返回给客户端的时候,会将已缓存的服务器响应首部作为响应首部的起点,然后在这基础上对首部进行了修改和扩充,以便于客户端的要求相匹配,而且还会插入新鲜度的值信息(Cache-control、Age、Expires首部)及一个Via首部来说明该请求来自代理缓存。 第四步:发送相应给客户端响应首部准备完毕后,缓存会将该响应返回给客户端。 HTTP 缓存的分类HTTP 可分为强缓存和协商缓存,两者的本质区别就在于是否要和服务器进行交互,详细如下: 第一类:强缓存在缓存未失效的情况下,可直接由缓存提供资源给客户端使用(状态码 200),而不用去请求服务端。缓存命中就属于强缓存。 和强缓存有关属性有(优先级由高到低):Pragma、Cache-Control、Expires Pragmahtml<meta http-equiv='Pragma' content='no-cache'/> 如果 html 的 meta 标签如果这样的话,它的意思是可以告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。这种方法使用上很简单,但只有部分浏览器可以支持,而且所有缓存代理服务器都不支持,因为代理不解析HTML内容本身。 上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。这种方法使用上很简单,但只有部分浏览器可以支持,而且所有缓存代理服务器都不支持,因为代理不解析HTML内容本身。 Expirehttp/1.0 提出,一个表示资源过期时间的 header,描述的是一个绝对时间,由服务器返回,值是用 GMT 格式的字符串表示,如:Expires:Thu, 31 Dec 2016 23:55:55 GMT ...

September 20, 2019 · 1 min · jiezi

session-cookietoken的区别及联系

sessionsession的中文翻译是“会话”,当用户打开某个web应用时,便与web服务器产生一次session。服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对cookie来说更安全,可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。 cookiecookie是保存在本地终端的数据。cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。 cookie的组成有:名称(key)、值(value)、有效域(domain)、路径(域的路径,一般设置为全局:"")、失效时间、安全标志(指定后,cookie只有在使用SSL连接时才发送到服务器(https))。下面是一个简单的js使用cookie的例子: 用户登录时产生cookie: document.cookie = "id="+result.data['id']+"; path=/";document.cookie = "name="+result.data['name']+"; path=/";document.cookie = "avatar="+result.data['avatar']+"; path=/";使用到cookie时做如下解析: var cookie = document.cookie;var cookieArr = cookie.split(";");var user_info = {};for(var i = 0; i < cookieArr.length; i++) { user_info[cookieArr[i].split("=")[0]] = cookieArr[i].split("=")[1];}$('#user_name').text(user_info[' name']);$('#user_avatar').attr("src", user_info[' avatar']);$('#user_id').val(user_info[' id']);tokentoken的意思是“令牌”,是用户身份的验证方式,最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。还可以把不变的参数也放进token,避免多次查库 cookie 和session的区别cookie数据存放在客户的浏览器上,session数据放在服务器上。cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session。session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用COOKIE。单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。所以个人建议:将登陆信息等重要信息存放为SESSION其他信息如果需要保留,可以放在COOKIE中token 和session 的区别session 和 oauth token并不矛盾,作为身份认证 token安全性比session好,因为每个请求都有签名还能防止监听以及重放攻击,而session就必须靠链路层来保障通讯安全了。如上所说,如果你需要实现有状态的会话,仍然可以增加session来在服务器端保存一些状态; App通常用restful api跟server打交道。Rest是stateless的,也就是app不需要像browser那样用cookie来保存session,因此用session token来标示自己就够了,session/state由api server的逻辑处理。 如果你的后端不是stateless的rest api, 那么你可能需要在app里保存session.可以在app里嵌入webkit,用一个隐藏的browser来管理cookie session. Session 是一种HTTP存储机制,目的是为无状态的HTTP提供的持久机制。所谓Session 认证只是简单的把User 信息存储到Session 里,因为SID 的不可预测性,暂且认为是安全的。这是一种认证手段。 而Token ,如果指的是OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对App 。其目的是让 某App有权利访问 某用户 的信息。这里的 Token是唯一的。不可以转移到其它 App上,也不可以转到其它 用户 上。 转过来说Session 。Session只提供一种简单的认证,即有此 SID,即认为有此 User的全部权利。是需要严格保密的,这个数据应该只保存在站方,不应该共享给其它网站或者第三方App。 所以简单来说,如果你的用户数据可能需要和第三方共享,或者允许第三方调用 API 接口,用 Token 。如果永远只是自己的网站,自己的 App,用什么就无所谓了。 ...

April 27, 2019 · 1 min · jiezi

HTTP缓存 - 强缓存/协商缓存/浏览器刷新

Web缓存:数据库缓存、服务器端缓存(代理服务器缓存、CDN 缓存)、浏览器缓存 浏览器缓存:HTTP 缓存、indexDB、cookie、localstorage 等等 HTTP缓存强制缓存的优先级高于协商缓存强缓存:命中缓存不需要和服务器端发生交互协商缓存:不管是否命中都要和服务器端发生交互流程: 强缓存Expires 定义:缓存过期的时间,超过了这个时间点就代表资源过期缺点:服务器时间,客户端时间可随意修改HTTP/1.0 的标准Cache-Control 由多个字段组合而成 max-age 指定一个时间长度,在这个时间段内缓存是有效的,单位是s(相对时间)no-store 禁止缓存,每次请求都要向服务器重新获取数据no-cache : max-age = 0仍然缓存,但是走协商缓存public 表明响应可以被任何对象(发送请求的客户端、代理服务器等等)Public 设置我们可以将 Http 响应数据存储到本地,但此时并不意味着后续浏览器会直接从缓存中读取数据并使用- 无法确定本地缓存的数据是否可用(可能已经失效)需要配合使用private 表明响应只能被单个用户(可能是操作系统用户、浏览器用户)缓存,是非共享的,不能被代理服务器缓存缓存数据标记为已过期只是告诉客户端不能再直接从本地读取缓存了,还可能被再次用到(协商缓存)cache-control使用 Cache-Control 的优先级更高,覆盖expire协商缓存浏览器第一次请求数据之后会将数据和响应头部的缓存标识存储起来。再次请求时会带上存储的头部字段,服务器端验证是否可用。如果返回 304 Not Modified,代表资源没有发生改变可以使用缓存的数据,获取新的过期时间。反之返回 200 就相当于重新请求了一遍资源并替换旧资源 Last-modified(响应头)/If-Modified-Since(请求头) 服务器端收到带 If-Modified-Since 的请求后会去和资源的最后修改时间对比。若修改过就返回最新资源,状态码 200,若没有修改过则返回 304注意: Last-modified 要记得配合 Expires/Cache-Control 使用,不设置,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样(根据响应头中2个时间字段 Date 和 Last-Modified 之间的时间差值,取其值的10%作为缓存时间周期。)Etag/If-None-Match: 由服务器端上生成的一段 hash 字符串,第一次请求时响应头带上 ETag: abcd,之后的请求中带上 If-None-Match: abcd,服务器检查 ETag,返回 304 或 200last-modified 和 Etag 区别 某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新。Last-modified 只能精确到秒。一些资源的最后修改时间改变了,但是内容没改变,使用 Last-modified 看不出内容没有改变。Etag 的精度比 Last-modified 高,属于强验证,要求资源字节级别的一致,优先级高。如果服务器端有提供 ETag 的话,必须先对 ETag 进行 Conditional Request实际使用考虑缓存的内容:css样式文件js文件logo、图标html文件可以下载的内容一些不应该被缓存的内容:业务敏感的 GET 请求不经常改变的文件给 max-age 设置一个较大的值,一般设置 max-age=31536000(一年)文件名称添加版本号、hash 值可能经常需要变动的文件:Cache-Control: no-cache / max-age=0浏览器几种刷新方式对缓存的影响1、在URI输入栏中输入然后回车 ...

April 22, 2019 · 1 min · jiezi

深入剖析浏览器缓存策略

前言在访问一个网页时,客户端会从服务器下载所需的资源。但是有些资源很少发生变动,例如 HTML、JS、CSS、图片、字体文件等。如果每次加载页面都从源服务器下载这些资源,不仅会增加获取资源的时间,也会给服务器带来一定压力。因此,重用已获取的资源十分重要。将请求的资源缓存下来,下次请求同一资源时,直接使用存储的副本,而不会再去源服务器下载。这就是我们常说的缓存技术。缓存的种类很多:浏览器缓存、网关缓存、CDN 缓存、代理服务器缓存等。这些缓存大致可以归为两类:共享缓存和私有缓存。共享缓存能够被多个用户使用,而私有缓存只能用于单个用户。浏览器缓存只存在于每个单独的客户端,因此它是私有缓存。本文主要介绍私有(浏览器)缓存。你将学习:浏览器缓存的分类如何启用和禁止缓存缓存存储的位置如何设置缓存的过期时间缓存过期之后会发生什么如何为自己的应用制定合适的缓存策略调试如何判断网站是否启用了缓存如何禁用浏览器缓存缓存存储启用缓存Cache-Control浏览器会根据 HTTP Response Headers 中的一些字段来决定是否要缓存该资源。通过设置 Response Headers 中的 Cache-Control 和 Expires 可以启用缓存,这样资源就会被缓存到客户端。Cache-Control 可以设置 private 、public 、max-age 、 no-cache 来启用缓存。Cache-Control: private/publicCache-Control: max-age=300Cache-Control: no-cacheprivate :表示该资源只能被浏览器缓存。public :表示该资源既能被浏览器缓存,也能被任何中间人(比如代理服务器、CDN 等)缓存。max-age :表示该资源能够被缓存的最大时间。如果设置 max-age=0 ,该资源仍然会被浏览器缓存,只不过立刻就过期了。no-cache :该资源会被缓存,但是立刻就过期了,因此需要先和服务器确认资源是否发生变化,只有当资源没有变化时,该缓存才会被使用,否则需要从服务器下载。相当于 max-age=0 。ExpiresExpires 标识了缓存的具体过期时间,来控制资源何时过期。通过设置 Expires 可以启用缓存。不过需要注意 Expires 的值是格林威治时间(Greenwich Mean Time, GMT),不是本地时间。Expires: Fri, 08 Mar 2029 08:05:59 GMTExpires: 0 // Expires: 0 仍然会启用缓存,只不过缓存立刻过期。优先级既然 Cache-Control 和 Expires 都能够启用缓存,那么问题来了,如果同时设置 Cache-Control: max-age=600 和 Expires: 0 ,那么浏览器应该如何缓存该资源呢?答案是只有 Cache-Control: max-age=600 生效。因为 Cache-Control 的优先级高于 Expires,如果同时设置了 Cache-Control 和 Expires,以 Cache-Control 为准。浏览器的默认行为设置 Cache-Control 之后,可以看到浏览器确实启用了缓存(from disk cache)。如下所示:Cache-Control:max-age=604800, must-revalidate, public但是我发现,即使 Response Header 中没有设置 Cache-Control 和 Expires,浏览器仍然会缓存某些资源。这是为什么呢?原来当 Response Header 中有 Last-Modified 但是没有 Cache-Control 和 Expires 时,浏览器会用一套自己的算法来决定这个资源会被缓存多长时间。这是浏览器为了提升性能进行的优化,每个浏览器的行为可能不一致,有些浏览器上甚至没有这样的优化。因此,如果要启用缓存,还是应该自己设置合适的 Cache-Control 和 Expires,不要依赖浏览器自身的缓存算法。当然,如果在调试时发现本应该更新的文件没有更新,也别忘了看看是否被浏览器缓存了。禁止缓存给 Cache-Control 设置 no-store 会禁止浏览器和中间人缓存该资源。在处理包含个人隐私数据或银行业务数据的资源时很有用。Cache-Control: no-store缓存目标对象一般来说,浏览器缓存只能存储 GET 响应,例如 HTML、JS、CSS、图片等静态资源。因为这些资源不经常发生变化,所以缓存可以帮助提升获取资源的速度。但是像一些 POST/DELETE 请求,这些请求基本上每一次都不一样,因此也没有什么缓存的价值。缓存位置浏览器可以在内存、硬盘中开辟一个空间用以保存请求资源的副本。我们经常在 Dev Tools 里面看到 Memory Cache(内存缓存)和 Disk Cache(硬盘缓存),指的就是缓存所在的位置。请求一个资源时,会按照优先级(Service Worker -> Memory Cache -> Disk Cache -> Push Cache)依次查找缓存,如果命中则使用缓存,否则发起网络请求。这里只介绍常用的 Memory Cache 和 Disk Cache。200 from Memory Cache表示不访问服务器,直接从内存中读取缓存。因为缓存的资源保存在内存中,所以读取速度较快,但是关闭进程之后,缓存的资源也会随之销毁。一般来说,系统不会给内存分配较大的容量,因此内存缓存一般用于存储小文件。同时,内存缓存在有时效性要求的场景下也很有用(比如浏览器的隐私模式)。200 from Disk Cache表示不访问服务器,直接从硬盘中读取缓存。与内存相比,硬盘的读取速度较慢,但是硬盘缓存持续的时间更长,关闭进程之后,缓存的资源仍然存在。由于硬盘的容量较大,因此一般用于存储大文件。总的来说就是:内存缓存:读取快、持续时间短、容量小硬盘缓存:读取慢、持续时间长、容量大缓存分类浏览器缓存一般分为两类:强缓存(也称本地缓存)和协商缓存(也称弱缓存)。判定过程如下:浏览器发送请求前,会先去缓存里面查看是否命中强缓存,如果命中,则直接从缓存中读取资源,不会发送请求到服务器。否则,进入下一步。当强缓存没有命中时,浏览器一定会向服务器发起请求。服务器会根据 Request Header 中的一些字段来判断是否命中协商缓存。如果命中,服务器会返回响应,但是不会携带任何响应实体,只是告诉浏览器可以直接从缓存中获取这个资源。否则,进入下一步。如果前两步都没有命中,则直接从服务器加载资源。强缓存和协商缓存的共同点在于,如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源。而不同点在于,强缓存不发送请求到服务器,而协商缓存会发送请求到服务器以验证资源是否过期。普通刷新会启用协商缓存,忽略强缓存。只有在地址栏或收藏夹输入网址、通过链接引用资源等情况下,浏览器才会启用强缓存。缓存过期策略当缓存过期之后,浏览器会向服务器发起 HTTP 请求,以确定资源是否发生了变化。如果资源未改变,那么浏览器会继续使用本地的缓存资源;如果该资源已经发生变化了,那么浏览器会删除旧的缓存资源,并将新的资源缓存到本地。过期时间Http Response Header 里面的 Cache-Control: max-age=xxx 和 Expires 都可以设置缓存的过期时间,但是它们有一些区别:Expires :标识该资源过期的时间点,它是一个绝对值,即在这个时间点之后,缓存的资源过期。max-age :标识该资源能够被缓存的最大的时间。它是一个相对值,相对于第一次请求该文档时服务器记录的「请求发起时间」。虽然 Cache-Control 是 HTTP 1.1 提出来的新特性,但并不是说 max-age 优于 Expires。它们都有各自的使用场景,我们应该根据业务需求去决定使用哪一个。比如当某个资源需要在特定的时间点过期时应该使用 Expires 。如果只是为了开启缓存,使用 max-age 可能会更好些,因为 Cache-Control 的优先级高于 Expires。针对应用中几乎不会改变的文件,通常可以设置一个较长的过期时间,以保证缓存的有效。例如图片、CSS、JS 等静态资源。缓存验证上一小节已经提到,当浏览器请求一个资源时,如果发现缓存中有该资源,但是已经过期了,那么浏览器就会向服务器发起 HTTP 请求,以验证缓存的资源是否发生变化。缓存验证时机什么时候会进行缓存验证?刷新页面。一般来说,为了确保用户获取到最新的数据,在刷新页面时大部分浏览器都不会再使用缓存中的数据,而是发起一个请求去服务器验证。Response Header 中设置了 Cache-control: must-revalidate。当缓存的资源过期之后,必须到源服务器去验证,只有确认该资源没有过期,才能继续使用缓存。缓存验证器服务器是怎么判断资源改变与否的呢?服务端在返回响应内容的同时,还会在 Response Header 中设置一些验证标识,当缓存的资源过期之后,浏览器就会携带验证标识向服务器发起请求,服务器通过对比这些标识,就能知道缓存的资源是否发生了改变。Header 中的验证标识字段主要有两组:Etag 和 If-None-Match 、Last-Modified 和 If-Modified-Since 。其中,形如 If-xxx 这样的请求首部字段,可以称之为条件请求。比如只在满足某个条件的情况下返回或上传文件,这样可以节省带宽。 Last-ModifiedLast-Modified 就是一个验证器。服务器在将资源返回给客户端的同时,会将资源的最后修改时间 Last-Modified 加在 Response Header 中一起返回。浏览器会为资源标记上该信息,当缓存过期之后,浏览器会把该信息设置到 Request Header 中的 If-Modified-Since 中向服务器发起请求。如果 If-Modified-Since 中的值和服务器上该资源最终的修改时间一致,就说明该资源没有被修改过,服务器会直接返回 304 状态码,无响应实体,这样就可以节省传输的数据量。如果不一致,服务器会返回 200 状态码,同时和第一次 HTTP 请求一样,返回响应实体和验证器。Last-Modified:Fri, 04 Jan 2019 14:00:21 GMTEtag服务器会通过某种算法,为资源计算出一个唯一标识符,在把响应返回给客户端的时候,会在 Response Header 中加上 Etag: 唯一标识符 一起返回给客户端。Etag:“952d03d8561454120b550f0a5679a172c4822ce8"客户端会将 Etag 保存下来,后续请求时会将 Etag 作为 Request Header 中 If-None-Match 的值发给服务器。通过比对客户端发过来的 Etag 和服务器上保存的 Etag 是否一致,就能够知道资源是否发生了变化。如果资源没有发生变化,返回 304,客户端继续使用缓存。如果资源已经修改,则返回 200。制定缓存策略缓存真的可以说让我们又爱又恨。在开发时,我们经常遇到这样的问题:明明已经修改了这个文件,为什么没有生效?好吧,文件被缓存了。。。但是在上线时,我们又希望文件尽可能地被浏览器缓存,来提高性能。因此为自己的应用制定合适的缓存策略非常重要。为静态资源设置较长缓存时间。有些资源很长时间都不会改变,比如一些三方库,图片,字体文件等。可以为它们设置一个很长的过期时间,例如设定「一年」。通过给文件名的唯一标识来确保文件修改生效。有些时候为了解决 bug,我们可能会修改一些文件,比如应用的 CSS、JS 等。如果这些文件已经被缓存,那么除非用户强制刷新页面,否则用户只有在缓存过期之后才有可能获取新的文件。如何让浏览器不使用缓存,而是重新下载新的文件呢?有一个办法就是给文件名加上唯一标识,比如 Hash 或版本信息。当文件修改之后,这个唯一标识也会随之改变。浏览器发现文件改变之后,就不会使用缓存了。明确是否有资源不能被缓存。比如一些敏感数据,如果不应该被浏览器缓存,需要在 Response Header 中设置 Cache-Control: no-store。调试如何知道请求的资源是否被缓存了?打开 Chrome 的开发者工具,我们可以看到 Size 这一栏下面,如果显示文件真实的大小,则说明该文件未被缓存。如果显示 from xxx cache,则说明该请求使用的是已被缓存的文件。如下:调试时,如果想禁用浏览器缓存,可以在开发者工具上勾选 Disabel cache。最后最后,大家可以通过下面这张图再回顾一下我们刚刚讲过的内容。参考HTTP 缓存奇怪的缓存策略 ...

April 9, 2019 · 2 min · jiezi

一文读懂Http Headers为何物(超详细)

一、HTTP 请求内容由于最新的http2,并没有被各大浏览器广泛使用,所以本文是基于http/1.1所编写的。同时经过检测我们也发现,chrome等浏览器也正是使用http/1.1版本的。关于http/1.1协议的详情,可查看官方文档我们打开chrome的network,点击任何一条request请求,即可发现,每个http headers都包含以下部分:Genaral,Response Headers,General(不属于headers,只用于收集请求url和响应的status等信息)Request Headers(请求headers)Response Headers(响应headers)Request Payload(请求参数)二、HTTP Headers分类在http heanders中,为了方便,分为以下几类:Genaral headers(和上面说的General不同,这个只是为了方便统计),Request Headers,Response Headers,Entity Headers(也是为了方便统计)。1、Genaral headers: 同时适用于请求和响应消息,但与最终消息主体中传输的数据无关的消息头。2、Request Headers: 包含更多有关要获取的资源或客户端本身信息的消息头。3、Response Headers:包含有关响应的补充信息,如其位置或服务器本身(名称和版本等)的消息头4、Entity Headers:包含有关实体主体的更多信息,比如主体长(Content-Length)度或其MIME类型(用于响应header中)。1、Genaral headersCache-Control——控制缓存的行为; 详情Connection——决定当前的事务完成后,是否会关闭网络连接; 详情Date——创建报文的日期时间; 详情Keep-Alive——用来设置超时时长和最大请求数;详情Via——代理服务器的相关信息;详情Warning——错误通知;详情Trailer——允许发送方在分块发送的消息后面添加额外的元信息; 详情Transfer-Encoding——指定报文主体的传输编码方式;详情Upgrade——升级为其他协议;2、Request headersAccept——客户端可以处理的内容类型;详情Accept-Charset——客户端可以处理的字符集类型;详情Accept-Encoding——客户端能够理解的内容编码方式;详情Accept-Language——客户端可以理解的自然语言;详情Authorization——Web 认证信息;详情Cookie——通过Set-Cookie设置的值;详情DNT——表明用户对于网站追踪的偏好;详情From——用户的电子邮箱地址;详情Host——请求资源所在服务器;详情If-Match——比较实体标记(ETag);详情If-Modified-Since——比较资源的更新时间;详情If-None-Match——比较实体标记(与 If-Match 相反);详情If-Range——资源未更新时发送实体 Byte 的范围请求;详情If-Unmodified-Since——比较资源的更新时间(与 If-Modified-Since 相反);详情Origin——表明了请求来自于哪个站点;详情Proxy-Authorization——代理服务器要求客户端的认证信息;详情Range——实体的字节范围请求;详情Referer——对请求中 URI 的原始获取方;详情TE——指定用户代理希望使用的传输编码类型;详情Upgrade-Insecure-Requests——表示客户端优先选择加密及带有身份验证的响应;详情User-Agent——浏览器信息;详情3、Response HeadersAccept-Ranges——是否接受字节范围请求;详情Age——消息对象在缓存代理中存贮的时长,以秒为单位;详情 Clear-Site-Data——表示清除当前请求网站有关的浏览器数据(cookie,存储,缓存);详情 Content-Security-Policy——允许站点管理者在指定的页面控制用户代理的资源;详情 Content-Security-Policy-Report-Only—— 详情ETag——资源的匹配信息;链接描述 Location——令客户端重定向至指定 URI;详情 Proxy-Authenticate——代理服务器对客户端的认证信息;详情 Public-Key-Pins——包含该Web 服务器用来进行加密的 public key (公钥)信息;详情 Public-Key-Pins-Report-Only——设置在公钥固定不匹配时,发送错误信息到report-uri;详情 Referrer-Policy——用来监管哪些访问来源信息——会在 Referer 中发送;详情 Server——HTTP 服务器的安装信息;详情 Set-Cookie——服务器端向客户端发送 cookie;详情 Strict-Transport-Security——它告诉浏览器只能通过HTTPS访问当前资源;详情 Timing-Allow-Origin——用于指定特定站点,以允许其访问Resource Timing API提供的相关信息;详情 Tk——显示了对相应请求的跟踪情况;详情 Vary——服务器缓存的管理信息;详情 WWW-Authenticate——定义了使用何种验证方式去获取对资源的连接;详情 X-XSS-Protection——当检测到跨站脚本攻击 (XSS)时,浏览器将停止加载页面;详情4、Entity HeadersAllow——客户端可以处理的内容类型,这种内容类型用MIME类型来表示;详情Content-Encoding——用于对特定媒体类型的数据进行压缩;详情 Content-Language——访问者希望采用的语言或语言组合;详情 Content-Length——发送给接收方的消息主体的大小;详情 Content-Location——替代对应资源的 URI;详情 Content-Range——实体主体的位置范围;详情 Content-Type——告诉客户端实际返回的内容的内容类型;详情 Expires——包含日期/时间, 即在此时候之后,响应过期;详情 Last-Modified——资源的最后修改日期时间;详情三、HTTP 具体应用1、CookieHTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使得它能够处理大量事务。HTTP/1.1 引入 Cookie 来保存状态信息。Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器之后向同一服务器再次发起请求时自动被携带上,用于告知服务端两个请求是否来自同一浏览器。由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)。Cookie 曾一度用于客户端数据的存储,因为当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API(本地存储和会话存储)或 IndexedDB。a、创建过程服务器发送的响应报文包含Set-Cookie首部字段,客户端得到响应报文后把 Cookie 内容保存到浏览器中。HTTP/1.1 200 OKContent-type: text/htmlSet-Cookie: PHPSESSID=kq8v6iujarsgflkeq7shmai9c7客户端之后对同一个服务器发送请求时,会从浏览器中取出 Cookie 信息并通过 Cookie 请求首部字段发送给服务器。GET /sample_page.html HTTP/1.1Host: www.example.orgCookie: PHPSESSID=kq8v6iujarsgflkeq7shmai9c7b、分类会话期 Cookie:浏览器关闭之后它会被自动删除,也就是说它仅在会话期内有效。持久性 Cookie:指定一个特定的过期时间(Expires)或有效期(max-age)之后就成为了持久性的 Cookie。安全 Cookie:指定HttpOnly,这样cookie不能使用 JavaScript 经由 Document.cookie 属性,来防范跨站脚本攻击(XSS)。HTTPS Cookie: 指定Secure,只有在请求使用SSL和HTTPS协议的时候才会被发送到服务器。Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;HttpOnlySet-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;Secure2、缓存降低客户端获取资源的延迟:缓存通常位于内存中,读取缓存的速度更快。并且缓存在地理位置上也有可能比源服务器来得近,例如浏览器缓存。实现方法:1、让代理服务器进行缓存;2、让客户端浏览器进行缓存a、使用 Cache-Control来控制缓存禁止进行缓存。no-store 规定不能对请求或响应的任何一部分进行缓存Cache-Control: 强制确认缓存。no-cache 指令规定缓存服务器需要先向源服务器验证缓存资源的有效性,只有当缓存资源有效才将能使用该缓存对客户端的请求进行响应。Cache-Control: no-cache缓存过期机制。max-age 指令出现在请求报文中,并且缓存资源的缓存时间小于该指令指定的时间,那么就能接受该缓存。max-age 指令出现在响应报文中,表示缓存资源在缓存服务器中保存的时间。或者使用Expires//请求中Cache-Control: max-age=31536000//响应中,优先处理max-ageCache-Control: max-age=31536000Expires: Wed, 04 Jul 2012 08:26:05 GMT缓存验证可以将缓存资源的值放入request header的 If-None-Match 首部,服务器收到该请求后,判断缓存资源的 值和资源的最新 值是否一致,如果一致则表示缓存资源有效,返回 304 Not Modified。并在response header中戴上 ETag 值//请求If-None-Match: W/“646-RJRVaOjMluW+SOAL0EThThA2lnM”//响应ETag: W/“646-RJRVaOjMluW+SOAL0EThThA2lnM"后续待更… ...

February 21, 2019 · 1 min · jiezi

不得不知道的浏览器http缓存

浏览器虽然发现了本地有该资源的缓存,但是不确定是否是最新的,于是想服务器询问,若服务器认为浏览器的缓存版本还可用,那么便会返回304。强缓存和协商缓存。1.浏览器请求某资源,通过header判断是否强缓存,若是强缓存,则从本地直接获取缓存文件,不发请求到浏览器2.若不是强缓存,发送请求到服务器,服务器通过一些request header确定是否是协商缓存,如果是,服务器将请求返回,但不返回资源,而是让客户端从本地缓存获取资源3.强缓存和协商缓存,资源都是本地,只是强缓存不会发送请求到服务器,协商缓存会发送请求到服务器。4.不是协商缓存,则浏览器将资源发送客户端。强缓存:服务端第一次响应请求时,告知浏览器还存在本地,设定时间,时间之内还获取该资源就从本地获取。Expires Cache-Control两个响应首部字段告知过期时间和最大生命周期。再次请求从缓存中找资源,若请求时间比Expires设定时间早则可用本地资源。http1.1 Cache-Control缓存资源最大生命周期,秒为单位。一起使用以Cache-Control为主。协商缓存:文件最后修改时间,服务器判断资源是否更新,未更新返回304表示not modified,浏览器从缓存加载。LastModified:资源最后更新时间,随服务器返回。if-modified-Since请求首部字段,通过比较两个时间判断资源是否修改。没有修改则协商缓存。过程描述:1.浏览器第一次请求资源,服务器响应,返回资源,响应头加Last-Modified。2.浏览器再次请求资源,在请求头加上if modified since,该值为上次Last-Modified的值3.服务器接受请求,将ifmodifiedsince值和资源最后修改值做对比,若一致则返回304,协商缓存。Etag周期性重写资源,但资源没变化,加注释等无关紧要信息。用Etag区分两个资源是否一致,随response返回和请求头的if-none-match相比较,判断资源在两次请求中是否修改,未修改则协商缓存。还有三种缓存方式:application cache,cookie,localstorage,sessionstorage那么,前端怎么实现呢?了解ifModifiedifModified (Boolean) : (默认: false) 仅在服务器数据改变时获取新数据。使用 HTTP 包 Last-Modified 头信息判断。由ifModified的定义可知,当ifModified设为true时,请求头会加上If-Modified-Since, If-Modified-Since是标准的http请求头标签,在发送http请求时,把浏览器端缓存页面的最后修改时间一起发到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行比较。如果时间一致,那么返回http状态码304(不返回文件内容)如果时间不一致,就返回http状态码200和新的文件内容,客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示到浏览器中。了解Last-ModifiedLast-Modified:表示该文件的最后修改日期,是文件属性和服务端没关系对于静态资源文件这是一个很有用的属性,请求静态资源文件时,请求头会携带一个If-Modified-Since:xxx(时间)属性,该属性是上一次请求时获取到的Last-Modified时间,如果本次请求的请求头时间与响应头时间一致,则返回304状态码,告诉浏览器你当前拥有的页面是最新的不需要获取新的数据实现function getAjax(url, sendData, state = true) { return new Promise((resolve, reject) => { $.ajax({ url: url, data: sendData, type: ‘get’, dataType: ‘json’, cache: !state, //是否使用浏览器的缓存数据 ifModified: state,//是否向服务器询问数据更新情况 success(data, des, status) { if (status.status === 200) { if (data.code === 200) { return resolve(data.data); } else { return reject({code: data.code, message: data.message}); } } if (status.status === 304) { getAjax(url, sendData, false) .then(data => { resolve(data); }) .catch(data => { reject(data); }); } }, error() { return reject({code: 503, message: ‘数据无法加载,请刷新重试!’}); } }); });}分析getAjax中传入3个参数,url接口地址,sendData 传输的数据,state状态值【代表ifModified的状态】首先向后台询问数据是否更新,ifModified的状态为true,不使用浏览器的缓存数据,cache设false当http状态码返回200时,说明数据更新了,直接使用服务器传输过来的新数据;当http状态码返回304时,说明数据没有发生改变,服务器不返回新数据,则向浏览器缓存请求数据,此时cache设true,ifModified的状态为false,不需要询问服务器数据是否更新。总结:使用缓存的目的就是在于减少计算,IO,网络等时间,可以快速的返回,特别是流量比较大的时候,可以节约很多服务器带宽和压力。 ...

December 31, 2018 · 1 min · jiezi

http缓存详细分析

每天系统复习一个知识点http缓存http缓存主要分为了两类 强缓存(本地缓存)和协商缓存浏览器在请求某一资源时,会先获取改资源缓存的header信息,判断是否命中强缓存(expires的信息和cache-control)若命中直接从缓存中获取该资源信息,包括缓存header信息,本次请求根本就不会与服务器进行通信。此为强缓存(本地缓存)如果没有命中强缓存,浏览器会发送请求到服务器,请求会携带第一次请求返回的的有关缓存的header字段信息(last-modified/if-modified-since 和 Etag/if-none-Match),由服务器根据请求中相关header信息来比对结果是否协商缓存命中,若命中,则服务器返回新的响应header信息更新缓存中的对应header信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取,否则返回最新的资源内容。 获取资源形式 状态码 发送请求到服务器强缓存 从缓存取 200(from cache) 否,直接从缓存取协商缓存 从缓存取 304(not modified) 是,正如其名,通过服务器来告知缓存是否可用强缓存相关的header字段1 expires,这是http1.0的规范,它的值为一个绝对时间的GMT格式的时间字符串,如Mon, 10 Jun 2015 21:31:12 GMT。如果发送请求的时间在expires之前,那么本地缓存始终有效,否则就会发送请求到服务器来获取资源。2 cache-control:max-age=number,这是Http1.1时出现的header信息。主要是利用该字段的max-age值来进行判断。它是一个相对值,资源第一次的请求时间和cache-control设定的有效期,计算出一个资源过期时间。再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就能命中缓存,否则就不行,cache-control除了该字段外,还有下面几个比较常用的设置值。 no-cache : 不使用本地缓存,需要使用协商缓存。 no-store : 直接禁止浏览器缓存数据。(强缓存和协商缓存都不行),每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。(常用于银行等重要业务) public : 可以被所有的用户缓存,包括终端用户和cdn等中间代理服务器 private : 只能被终端用户缓存,不允许CDN等中继缓存服务器对其缓存注意:如果cache-control与expires同时存在的话,cache-control的优先级高于expires。协商缓存协商缓存都是由服务器来确定缓存资源是否可用的,所以客户端与服务器端通过某种标识进行通信,从而让服务器判断请求资源是否可以缓存访问,这里涉及到下面两组header字段。这两组搭档都是成对出现的,即第一次请求的响应头带上某个字段(last-modified或者ETag),则后续请求则会带上对应的请求字段(if-modified-since或者if-none-match),若响应头没有last-modified或者Etag字段,则请求头也不会有对应的字段。1,第一次和服务器交互,服务器返回资源 在response的header加上last-modified的header.这个header表示这个资源在服务器上的最后修改时间2,第二次请求这个资源,浏览器会在request header加上if-modified-since的header.这个header的值就是上一次请求时返回的last-modified的值。服务器再次收到资源请求。根据浏览器传过来的if-modified-since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有发生变化则返回304 not modified .但是不会返回资源内容。如果有变化,就正常返回资源内容和更新last-modified字段。当服务器返回304 not modified的响应时,response header中不会再添加last-modified的字段。因为既然资源没有变化,那么last-modified也就不会改变.Etag/if-none-Match这两个值是由服务器生产的每一个资源的唯一标识字符串,只要资源有变化就这个值就会改变,其判断过程和last-modified/if-modified-since类似,与last-modified不一样的是。当服务器返回304 notmodified的响应 response header中还会把这个etag返回,即使这个eTag跟之前没有变化。Etag比较的是文件资源的特征值,而Last-Modifield则比较的是文件资源的最后的修改时间。这两个其实是相辅相成的,不是有了Etag就不该有Last-Modifield,有了Last-Modifield就不该有Etag,同时传入服务器时,服务器会根据自己的缓存机制进行选择要使用哪个,甚至可以两个都进行参考比如img肯定判断last-modified更方便。其他文件可能比较etag更方便既生last-modifed何生ETag你可能会觉得使用last-modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还要Etag呢。http1.1 etag的出现主要是为了解决几个last-modifed比较难解决的问题:1 一些文件也行会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;2 某些文件修改非常频繁,比如在秒以下的时间内进行修改(比方说1s内修改N次)if-modified-since能检查到的粒度是s级的,这种修改无法判断(unix记录mtime只能精确到秒)3 某些服务器不能精确得到文件的最后修改时间。不能缓存的请求

December 21, 2018 · 1 min · jiezi

HTTP缓存(Cache-Control、Expires 、ETag)

HTTP缓存HTTP缓存( ETag、Cache-Control)——谷歌开发者HTTP缓存有利于web性能优化Cache-Control例子假设我们首页有一个请求,请求js文件<script src="./main.js"></script>如何让CSS和JS请求速度加快?此时打开首页发现这个文件大小为279KB,使用时间为382ms如果再次刷新首页,那么这个文件还会被再次请求一次。那么如何重复利用之前获取的资源而不用反复请求呢?答案是HTTP缓存,这是性能优化的一个重要方面。接下来在响应里设置响应头Cache-Control: max-age=30刷新两次首页第二次的时间为0响应头中的Cache-Control: max-age=30表示客户端将这个缓存最多 保存30 秒,30秒后再次请求文件将会再次下载。即:设置这个响应头之后,浏览器请求时发现是相同的URL,浏览器直接从内存里返回已经缓存的main.js,没有向服务器发出请求问题为什么首页不设置Cache-Control呢?如果首页缓存,刷新首页的时候根本不会请求服务器,那么如果服务器更新了代码,浏览器将没有办法接收到新的版本。一般首页,HTML不要设置Cache-Control。js和css要设置久一点例如10年,即一直保留有缓存。那么js和css更新了怎么办?浏览器请求时发现是相同的URL才使用缓存,那么可以设置查询参数,例如第二个版本的js可以写<script src="./main.js?v=2"></script>,来保证URL的不同,重新获取新的js文件。这样即可以缓存很久,又可以随时更新例如知乎的网页里的请求:总结通过网络获取内容既速度缓慢又开销巨大。较大的响应需要在客户端与服务器之间进行多次往返通信,这会延迟浏览器获得和处理内容的时间,还会增加访问者的流量费用。因此,缓存并重复利用之前获取的资源的能力成为性能优化的一个关键方面。好在每个浏览器都自带了 HTTP 缓存实现功能。您只需要确保每个服务器响应都提供正确的 HTTP标头指令,以指示浏览器何时可以缓存响应以及可以缓存多久。ExpiresExpires 是以前用来控制缓存的http头,Cache-Control是新版的API。现在首选 Cache-Control。如果在Cache-Control响应头设置了 “max-age” 或者 “s-max-age” 指令,那么 Expires 头会被忽略。响应头设置方式:Expires: Wed, 21 Oct 2015 07:28:00 GMTExpires 响应头包含日期/时间, 即在此时候之后,响应过期。注意: 因为过期标准的时间用的是本地时间,所以不靠谱,所以要游侠使用Cache-Control代替Expires区别Cache-Control设置时间长度Expires 设置时间点详细:Expires - HTTP | MDNMD5MD5是消息摘要算法。用于确保信息传输完整一致。具体作用这样接受一个String 或 Buffer,返回一个固定的String如果接受的String改变,那么返回的String也会改变例如将1.txt中的其中一个1改为0,那么返回值如下可见返回至完全改变了这个特性可以用来判断两次信息传输是否完整一致ETag例子:例如我们请求一个js文件。设置一个ETag响应头设置的ETage响应头为这个JS文件的MD5值查看响应:那么:下一次请求这个JS的时候,浏览器会把上一次响应的那个ETage的值放到If-None-Match里面,如图:这样做的作用是:如果请求和响应的MD5一样,说明不需要重新下载这个js文件。这时我们修改代码:如果MD5一样,说明文件没改过,那么返回304304 Not Modified:HTTP 304 未改变说明无需再次传输请求的内容,也就是说可以使用缓存的内容。HTTP 304 没有响应体,因为不需要下载响应内容,直接用缓存就行了ETag与 Cache-Control的区别假设我们请求两个文件,CSS文件使用Cache-Control缓存,js文件使用ETag。代码如下:两个请求区别:所以:由于CSS的请求是用缓存(Cache-Control)的,所以直接不发请求而js用的ETag,有请求也有响应,只不过如果MD5一样,那么就不下载响应体我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/dev…

October 17, 2018 · 1 min · jiezi