关于浏览器缓存:浏览器缓存机制

罕用的缓存Memory CacheMemory Cache 也就是内存中的缓存,次要蕴含的是以后中页面中曾经抓取到的资源,例如页面上曾经下载的款式、脚本、图片等。读取内存中的数据必定比磁盘快,内存缓存尽管读取高效,可是缓存持续性很短,会随着过程的开释而开释。 一旦咱们敞开 Tab 页面,内存中的缓存也就被开释了。那么既然内存缓存这么高效,咱们是不是能让数据都寄存在内存中呢?这是不可能的。计算机中的内存肯定比硬盘容量小得多,操作系统须要精打细算内存的应用,所以能让咱们应用的内存必然不多。须要留神的事件是,内存缓存在缓存资源时并不关怀返回资源的HTTP缓存头Cache-Control是什么值,同时资源的匹配也并非仅仅是对URL做匹配,还可能会对Content-Type,CORS等其余特色做校验。 Disk CacheDisk Cache 也就是存储在硬盘中的缓存,读取速度慢点,然而什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上。在所有浏览器缓存中,Disk Cache 覆盖面根本是最大的。它会依据 HTTP Herder 中的字段判断哪些资源须要缓存,哪些资源能够不申请间接应用,哪些资源曾经过期须要从新申请。并且即便在跨站点的状况下,雷同地址的资源一旦被硬盘缓存下来,就不会再次去申请数据。绝大部分的缓存都来自 Disk Cache浏览器会把哪些文件丢进内存中?哪些丢进硬盘中?对于这点,网上说法不一,不过以下观点比拟靠得住:对于大文件来说,大概率是不存储在内存中的,反之优先以后零碎内存使用率高的话,文件优先存储进硬盘 资源自身大小数值当http状态为200是实实在在从浏览器获取的资源,当http状态为304时该数字是与服务端通信报文的大小,并不是该资源自身的大小,该资源是从本地获取的 chrome采取措施的准则什么时候是from memory cache 什么时候是from disk cache 呢?即哪些资源会放在内存当中,哪些资源浏览器会放在磁盘上呢,后果如下下表所示 状态类型阐明200form memory cache <p>不申请网络资源,资源在内存当中,个别脚本、字体、图片会存在内存当中</p> 200form disk ceche不申请网络资源,在磁盘当中,个别非脚本会存在内存当中,如css等200资源大小数值从服务器下载最新资源304报文大小申请服务端发现资源没有更新,应用本地资源不同浏览器策略是否统一以上的数据及统计都是在chrome浏览器下进行的在Firefox下并没有from memory cache以及from disk cache的状态展示雷同的资源在chrome下是from disk/memory cache,然而Firefox通通是304状态码即Firefox下会缓存资源,然而每次都会申请服务器比照以后缓存是否更改,chrome不申请服务器,间接拿过去用这也是为啥chrome比拟快的起因之一吧, 强缓存强缓存:不会向服务器发送申请,间接从缓存中读取资源,在chrome控制台的Network选项中能够看到该申请返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存能够通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。 1.Expires缓存过期工夫,用来指定资源到期的工夫,是服务器端的具体的工夫点。也就是说,Expires=过期工夫。Expires是Web服务器响应音讯头字段,在响应http申请时通知浏览器在过期工夫前浏览器能够间接从浏览器缓存取数据,而无需再次申请。Expires 是 HTTP/1 的产物,受限于本地工夫,如果批改了本地工夫,可能会造成缓存生效。Expires: Wed, 22 Oct 2018 08:41:00 GMT示意资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期,须要再次申请。 ...

May 24, 2021 · 1 min · jiezi

浏览器缓存看这一篇就够了

浏览器缓存作为性能优化的重要一环,对于前端而言,重要性不言而喻。以前总是一知半解的,所以这次好好整理总结了一下。1、缓存机制首先我们来总体感知一下它的匹配流程,如下:浏览器发送请求前,根据请求头的expires和cache-control判断是否命中(包括是否过期)强缓存策略,如果命中,直接从缓存获取资源,并不会发送请求。如果没有命中,则进入下一步。没有命中强缓存规则,浏览器会发送请求,根据请求头的last-modified和etag判断是否命中协商缓存,如果命中,直接从缓存获取资源。如果没有命中,则进入下一步。如果前两步都没有命中,则直接从服务端获取资源。2、强缓存强缓存:不会向服务器发送请求,直接从缓存中读取资源。2.1 强缓存原理强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程,强制缓存的情况主要有三种(暂不分析协商缓存过程),如下:第一次请求,不存在缓存结果和缓存标识,直接向服务器发送请求存在缓存标识和缓存结果,但是已经失效,强制缓存是啊比,则使用协商缓存(暂不分析)存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果那么强制缓存的缓存规则是什么?当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Control优先级比Expires高。2.1.1、 Expires缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。也就是说,Expires=max-age + 请求时间,需要和Last-modified结合使用。Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。Expires 是 HTTP/1 的产物,受限于本地时间,如果修改了本地时间,可能会造成缓存失效。2.1.2、 Cache-Control在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存,主要取值为:public:所有内容都将被缓存(客户端和代理服务器都可缓存)private:所有内容只有客户端可以缓存,Cache-Control的默认取值no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效需要注意的是,no-cache这个名字有一点误导。设置了no-cache之后,并不是说浏览器就不再缓存数据,只是浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致,也就是协商缓存。而no-store才表示不会被缓存,即不使用强制缓存,也不使用协商缓存2.1.3、设置强缓存需要服务端设置expires和cache-control。nginx代码参考,设置了一年的缓存时间:location ~ ..(ico|svg|ttf|eot|woff)(.) { proxy_cache pnc; proxy_cache_valid 200 304 1y; proxy_cache_valid any 1m; proxy_cache_lock on; proxy_cache_lock_timeout 5s; proxy_cache_use_stale updating error timeout invalid_header http_500 http_502; expires 1y;}浏览器的缓存存放在哪里,如何在浏览器中判断强制缓存是否生效?这就是下面我们要讲到的from disk cache和from memory cache。2.2、from disk cache和from memory cache细心地同学在开发的时候应该注意到了Chrome的网络请求的Size会出现三种情况from disk cache(磁盘缓存)、from memory cache(内存缓存)、以及资源大小数值。状态类型说明200form memory cache不请求网络资源,资源在内存当中,一般脚本、字体、图片会存在内存当中200form disk ceche不请求网络资源,在磁盘当中,一般非脚本会存在内存当中,如css等200资源大小数值从服务器下载最新资源304报文大小请求服务端发现资源没有更新,使用本地资源浏览器读取缓存的顺序为memory –> disk。以访问https://github.com/xiangxingchen/blog为例我们第一次访问时https://github.com/xiangxingchen/blog关闭标签页,再此打开https://github.com/xiangxingchen/blog时F5刷新时简单的对比一下3、协商缓存协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:协商缓存生效,返回304和Not Modified协商缓存失效,返回200和请求结果3.1、Last-Modified和If-Modified-Since浏览器首先发送一个请求,让服务端在response header中返回请求的资源上次更新时间,就是last-modified,浏览器会缓存下这个时间。然后浏览器再下次请求中,request header中带上if-modified-since:[保存的last-modified的值]。根据浏览器发送的修改时间和服务端的修改时间进行比对,一致的话代表资源没有改变,服务端返回正文为空的响应,让浏览器中缓存中读取资源,这就大大减小了请求的消耗。由于last-modified依赖的是保存的绝对时间,还是会出现误差的情况:保存的时间是以秒为单位的,1秒内多次修改是无法捕捉到的;各机器读取到的时间不一致,就有出现误差的可能性。为了改善这个问题,提出了使用etag。3.2、ETag和If-None-Matchetag是http协议提供的若干机制中的一种Web缓存验证机制,并且允许客户端进行缓存协商。生成etag常用的方法包括对资源内容使用抗碰撞散列函数,使用最近修改的时间戳的哈希值,甚至只是一个版本号。 和last-modified一样.浏览器会先发送一个请求得到etag的值,然后再下一次请求在request header中带上if-none-match:[保存的etag的值]。通过发送的etag的值和服务端重新生成的etag的值进行比对,如果一致代表资源没有改变,服务端返回正文为空的响应,告诉浏览器从缓存中读取资源。etag能够解决last-modified的一些缺点,但是etag每次服务端生成都需要进行读写操作,而last-modified只需要读取操作,从这方面来看,etag的消耗是更大的。二者对比精确度上:Etag要优于Last-Modified。优先级上:服务器校验优先考虑Etag。性能上:Etag要逊于Last-Modified4、用户行为对浏览器缓存的影响打开网页,地址栏输入地址: 查找 disk cache 中是否有匹配。如有则使用;如没有则发送网络请求。普通刷新 (F5):因为 TAB 并没有关闭,因此 memory cache 是可用的,会被优先使用(如果匹配的话)。其次才是 disk cache。强制刷新 (Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有 Cache-control:no-cache(为了兼容,还带了 Pragma:no-cache),服务器直接返回 200 和最新内容。5、总结 ...

March 31, 2019 · 1 min · jiezi

sessionStorage和localStorage

H5前端存储 localStorage 和 sessionStorage简述曾在项目中多次使用过localStorage和sessionStorage来存放token,但一直未深入了解。近期项目压力极小,就看了很多文章研究了一下,并结合项目经验做个总结。session 和 sessionStorage,Java 和 JavaScript在彻底弄懂session,cookie,token中,我已经讲过session。在我学习sessionStorage的过程中,看到很多文章的评论说:sessionStorage不是存在服务器的吗?在这里,我说明一下,session是存放于服务器的一个状态集合,而sessionStorage是H5新引入的一个客户端存储数据的空间,与session并无关系,大家千万不要搞混了。就像Java和JavaScript,只是名字长得像而已。localStorage和sessionStorage之间有些异同,可以进行比较用法用法很简单,sessionStorage和localStorage的api一样。// 保存数据到sessionStoragesessionStorage.setItem(“key”, “value”);// 从sessionStorage获取数据const data = sessionStorage.getItem(“key”);// 从sessionStorage删除保存的数据sessionStorage.removeItem(“key”);// 从sessionStorage删除所有保存的数据sessionStorage.clear();// 从sessionStorage获取全部数据const allData=sessionStorage.valueOf();异同相同点localStorage和sessionStorage一样都是用来存储客户端临时信息的对象。以chrome为例他们均只能存储字符串类型的对象存储大小都为5M都遵守同源策略不同点sessionStorage有期限,当窗口或浏览器关闭时就会被销毁。localStorage无限期,关闭浏览器后仍存在,除非用户手动在浏览器UI层删除localStorage 在同源同域同端口的不同窗口下可共享,在不同浏览器中不可共享sessionStorage 在同源同域同端口的不同窗口下不可共享。注意这里的不同窗口是指浏览器另起一窗口,并不是指页面路由跳转小结在我做过的项目中,storage一般用来存储少量的用户信息和token,建议大家不要把什么数据都放在 localStorage 和 sessionStorage中,毕竟前端的安全性太低。只要打开控制台就可以任意的修改localStorage 和 sessionStorage的数据。重要的信息最好还是放在后台。谢谢最后 如果大家有疑惑可以随便找一个小说网站在控制台试一试,很快便可掌握。本文如有错误,欢迎指出。

January 10, 2019 · 1 min · jiezi

JavaScript之数据属性和访问器属性

在javaScript中,对象的属性分为两种类型:数据属性和访问器属性。数据属性数据属性包含的是一个数据值的位置,在这可以对数据值进行读写。数据属性包含四个特性,分别是:configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或能否把属性修改为访问器属性,默认为trueenumerable:表示能否通过for-in循环返回属性writable:表示能否修改属性的值value:包含该属性的数据值。默认为undefined访问器属性访问器属性不包含数据值,包含的是一对get和set方法,在读写访问器属性时,就是通过这两个方法来进行操作处理的。访问器属性包含的四个特性:configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或能否把属性修改为访问器属性,默认为falseenumerable:表示能否通过for-in循环返回属性,默认为falseGet:在读取属性时调用的函数,默认值为undefinedSet:在写入属性时调用的函数,默认值为undefined属性的读取与修改对象的属性通过 Object.getOwnPropertyDescriptor() 获取对象的属性通过 Object.defineProperty() 修改数据属性和访问器属性是同级别的关系,只是由于功能不同把它们分成两派,按照它们所谓的 “特征值” 定义这个属性的性质。访问器属性只是因为它带有可以访问对象内其它属性的功能(通过 getter、setter 函数),并经过一些处理从而实现 “设置一个属性的值会导致其他属性发生变化”的效果。如果一个对象属性同时有(value或writable)和(get或set)关键字,将会产生一个异常如果只指定get方法,不指定set方法,那么这个属性是只读的,反之则是只写的let obj = {a:1,_b:2}Object.getOwnPropertyDescriptor(obj,‘a’) /* { value: 1, writable: true, enumerable: true, configurable: true } ///修改数据属性Object.defineProperty(obj,‘a’,{ value: 100, writable: false, enumerable: false, configurable: true})Object.getOwnPropertyDescriptor(obj,‘a’) / { value: 100, writable: false, enumerable: false, configurable: true } */// 修改访问器属性Object.defineProperty(obj,‘b’,{ get(){ return this._b }, set(newVal){ this._b = this._b + newVal },})obj.b = 5console.log(obj.b) // 7

January 3, 2019 · 1 min · jiezi

前端性能优化总结

1.原则多使用内存,缓存或者其他方法减少CPU计算,减少网络请求减少IO操作(硬盘读写)2.加载资源优化静态资源的合并和压缩。静态资源缓存(浏览器缓存策略)。使用CDN让静态资源加载更快。3. 渲染优化CSS放head中,JS放body后图片懒加载减少DOM操作,对DOM操作做缓存减少DOM操作,多个操作尽量合并在一起执行事件节流尽早执行操作 DOMContentLoaded4. 示例4.1 资源合并a.js b.js c.js — abc.js4.2 缓存通过连接名称控制缓存<script src=“abc_1.js” ></script>只有改变内容的时候,链接名称才会改变。4.3 懒加载 <img src=“preview.png” realsrc=“abc.png” id=“img1” /> <script> var i = document.getElementById(‘img1’); i.src = i.getAttribute(‘realsrc’); </script>4.4 缓存dom查询 //没有缓存dom for (let i = 0; i < document.getElementsByTagName(‘p’).length; i++) { } //缓存dom var p = document.getElementsByTagName(‘p’); for (let i = 0; i < p.length; i++) { }4.5 合并dom插入 var listNode = document.getElementById(’list’); var flag = document.createDocumentFragment(); var li; for (let i = 0; i < 10; i++) { li = document.createElement(’li’); li.innerHTML = i; flag.appendChild(li); } listNode.appendChild(flag);10次dom插入 —> 1次dom插入4.6 事件节流监听文字改变事件,无操作100毫秒后执行操作,不用每次触发。 var textarea = document.getElementById(’ta’); var timeoutId; textarea.addEventListener(‘keyup’,function(){ if(i){ clearTimeout(i); } timeoutId = setTimeout(() => { //操作 }, 100); });事件节流主要用于触发频率较高的事件,设定一个缓冲触发事件。补充异步加载非核心代码异步加载 – 异步加载的方式 – 区别1.动态脚本加载用js创建2.defer3.async<script src=“script.js”></script>没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。<script async src=“script.js”></script>有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。<script defer src=“myscript.js”></script>有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。关于 defer,我们还要记住的是它是按照加载顺序执行脚本的标记为async的脚本并不保证按照指定它们的先后顺序执行。对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行。浏览器缓存总结的非常好浏览器缓存 – 缓存的分类 – 缓存的原理缓存就是html文件在本地存在的副本,强缓存发现有缓存直接用。Expires: 绝对时间,判断客户端日期是否超过这个时间Cache-Control:相对时间,判断访问间隔是否大于3600秒//在设定时间之前不会和服务端进行通信了//如果两个都下发以后者为准协商缓存询问服务器缓存是否可以用,在进行判断是否用。Last-Modified/If-Modified-Since第一次请求,respone的header加上Last-Modified(最后修改时间)再次请求,在request的header上加上If-Modified-Since 和服务端的最后修改时间对比,如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。浏览器收到304的响应后,就会从缓存中加载资源如果协商缓存没有命中,浏览器直接从服务器加载资源时,Last-Modified的Header在重新加载的时候会被更新Etag/If-None-Match这两个值是由服务器生成的每个资源的唯一标识字符串,只要资源有变化就这个值就会改变;其判断过程与Last-Modified/If-Modified-Since类似,他可以精确到秒的更高级别。DNS预解析<meta http-equiv=“x-dns-prefetch-control” content=“on”><link rel=“dns-prefetch” href="//www.zhix.net">在一些浏览器的a标签是默认打开dns预解析的,在https协议下dns预解析是关闭的,加入mate后会打开。 ...

December 28, 2018 · 1 min · jiezi

浏览器缓存小结

一. 分类浏览器的缓存,从状态码来看一共有两种304:确认没有修改200:不发请求,直接读取缓存从设置方式来看,有四种(暂不考虑Service Worker)maxAgeApplication CacheLast-Modified/If-Modified-SinceEtag/If-None-MatchmaxAge设置方法:var expires = new Date();var maxAge = 606024*365;expires.setTime(expires.getTime() + maxAge * 1000);response.setHeader(“Expires”, expires.toUTCString());response.setHeader(“Cache-Control”, “max-age=” + maxAge);说明:浏览器在发送请求之前由于检测到Cache-Control和Expires(Cache-Control的优先级高于Expires,但有的浏览器不支持Cache-Control,这时采用Expires), 如果没有过期,则不会发送请求,而直接从缓存中读取文件。Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。 只不过Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于Expires。备注:chrome中只有通过链接跳转访问才可以,f5是不管用的,‘Cache-Control’ is always set to ‘max-age=0′Application Cache因为大量的bug已经不建议使用,略Last-Modified/If-Modified-Since设置方法fs.stat(realPath, function (err, stat) { var lastModified = stat.mtime.toUTCString(); var ifModifiedSince = “If-Modified-Since”.toLowerCase(); response.setHeader(“Last-Modified”, lastModified); if (request.headers[ifModifiedSince] && lastModified == request.headers[ifModifiedSince]) { response.writeHead(304, “Not Modified”); response.end(); }})说明:response 设置Last-Modified头,request便会带上If-Modified-Since头,需要手动比较,并返回304备注Last-Modified标注的最后修改只能精确到秒级;有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形。Etag/If-None-Match设置方法var hash = crypto.createHash(‘md5’).update(file).digest(‘base64’);response.setHeader(“Etag”, hash);if (request.headers[‘if-none-match’] && request.headers[‘if-none-match’] === hash) { response.writeHead(304, “Not Modified”); response.end(); return;}说明:response设置Etag头,request便会自动带上if-none-match头;需要手动比较,并返回304适用于文件更新,但是内容并没有修改的情况,比如目前前端的打包。流程图 graph TB start(浏览器请求) –> hasAppcache{appcache?} hasAppcache – YES –> 200cache[200 从缓存读取] hasAppcache – NO –> ce{Cache-Control/Expires</br>是否有效} ce – YES –> 200cache ce – NO –> etag{has Etag?} etag – YES –> ifNoMatch[向服务器请求带if-None-Match] etag – NO –> lastModify{has Last-modified?} lastModify – YES –> hasLastModify[向服务器请求带if-Modified-Since] lastModify == NO ==> 200server[200 从服务器读取] ifNoMatch –> match{match?} match -. YES .-> 304cache[304 从缓存读取] match == NO ==> 200server hasLastModify –> lessThenModifiedSince{lastModified</br><=</br>ifModifiedSince?} lessThenModifiedSince -. YES .-> 304cache lessThenModifiedSince == NO ==> 200server 参考文章 https://github.com/etoah/BrowserCachePolicy ...

December 28, 2018 · 1 min · jiezi