当前位置: 首页 > 科技观察

深入理解前端性能监控

时间:2023-03-23 11:57:17 科技观察

在同一个网络环境下,有两个网站也能满足你的需求。你选择,你会使用哪一个?页面的性能是前端开发中的一个重要环节,但是我们一直没有更好的方法来测试页面的性能。直到W3C性能组推出新的APIwindow.performance,目前IE9以上的浏览器都支持。它是浏览器中用来记录页面加载和解析过程中关键时刻的对象。放置在全局环境中,可以通过JavaScript访问。使用performanceAPI,可以使用如下方法检测并兼容performance:varperformance=window.performance||window.msPerformance||window.webkitPerformance;if(performance){//yourcode}先来了解一下结构ofperformance:performance.memory表示当前内存使用情况,是一个动态值,其中:usedJSHeapSize表示:JS对象(包括V8引擎内部对象)占用的内存数量totalJSHeapSize表示:可用内存jsHeapSizeLimit表示:内存大小限制通常,usedJSHeapSize不能大于totalJSHeapSize,如果大于,则可能存在内存泄漏。performance.navigation显示页面的来源信息,其中:redirectCount表示:如果有重定向,页面经过几次重定向跳转,默认为0type表示页面打开方式,0表示TYPE_NAVIGATENEXT正常进入页面(非刷新、非重定向等)1表示TYPE_RELOAD页面通过window.location.reload()刷新2表示TYPE_BACK_FORWARD页面通过浏览器的前进后退按钮进入(历史记录)255表示TYPE_UNDEFINED页面不是通过以上方法进入的performance.onresourcetimingbufferfull属性是一个事件处理程序,当resourcetimingbufferfull事件被触发时将被调用。它的值是一个手动设置的回调函数,会在浏览器的资源时间性能缓冲区满时执行。performance.timeOrigin是一系列时间点的参考点,精确到万分之一毫秒。performance.timing是一系列的关键时间点,包括网络、分析等一系列时间数据。下面是对这几个时间点timing的解释:{//同一浏览器上页面卸载(unload)结束时的时间戳。如果没有上一页,则此值将与fetchStart相同。navigationStart:1543806782096,//上一页unload事件抛出时的时间戳。如果没有上一页,该值将返回0。unloadEventStart:1543806782523,//对应unloadEventStart,卸载事件处理完成时的时间戳。如果没有上一页,这个值将返回0。unloadEventEnd:1543806782523,//第一次HTTP重定向开始的时间戳。如果没有重定向,或者重定向中有不同的来源,这个值将返回0。redirectStart:0,//最后一次HTTP重定向完成的时间戳(即HTTP响应的最后一位被发送的时间)直接收到)。//如果没有重定向,或者重定向中有不同的来源,这个值将返回0.redirectEnd:0,//浏览器准备好使用HTTP请求获取(fetch)文档的时间戳。这一点将在检查任何应用程序缓存之前。fetchStart:1543806782096,//DNS域名查询开始的UNIX时间戳。//如果使用长连接,或者这个信息存在缓存或者本地资源中,这个值会和fetchStart保持一致。domainLookupStart:1543806782096,//DNS域名查询完成的时间//如果使用本地缓存(即没有DNS查询)或者长连接,则等于fetchStart值domainLookupEnd:1543806782096,//时间HTTP(TCP)域名查询结束时戳记。//如果使用长连接,或者这个信息存在缓存或者本地资源中,这个值会和fetchStart保持一致。connectStart:1543806782099,//HTTP(TCP)返回浏览器与服务器建立连接时的时间戳。//如果建立了持久连接,则返回值等于fetchStart属性的值。连接建立是指所有握手和认证过程结束。connectEnd:1543806782227,//HTTPS返回浏览器和服务器开始安全链接握手的时间戳。如果当前网页不需要安全连接,则返回0。secureConnectionStart:1543806782162,//返回浏览器向服务器发送HTTP请求时(或开始读取本地缓存时)的时间戳。requestStart:1543806782241,//返回浏览器从服务器收到(或从本地缓存中读取)第一个字节时的时间戳。//如果发起请求后传输层失败,重新打开连接,则该属性将被计为新请求对应的发起时间。responseStart:1543806782516,//当浏览器从服务器接收到最后一个字节时返回(或从本地缓存中读取,或从本地资源中读取)//(如果在此之前HTTP连接已经关闭,关闭时返回)的时间戳。responseEnd:1543806782537,//当前网页DOM结构开始解析时的时间戳(即Document.readyState属性变为“loading”时触发对应的readystatechange事件)。domLoading:1543806782573,//当前网页的DOM结构解析结束,嵌入资源开始加载时的时间戳(即Document.readyState属性变为“interactive”时,对应的readystatechange事件被触发)。domInteractive:1543806783203,//当解析器发送DOMContentLoaded事件时,即所有需要执行的脚本都解析完毕的时间戳。domContentLoadedEventStart:1543806783203,//所有需要立即执行的脚本都执行完毕的时间戳(与执行顺序无关)。domContentLoadedEventEnd:1543806783216,//当前文档解析完成时的时间戳,即Document.readyState变为'complete'并触发相应的readystatechange时的时间戳domComplete:1543806783796,//加载事件发送时的时间戳。如果事件还没有发送,其值为0。loadEventStart:1543806783796,//加载事件结束时,即加载事件完成时的时间戳。如果这个事件没有发送或者完成,那么它的值为0。loadEventEnd:1543806783802}这些参数非常有用,可以帮助我们获取页面的Domready时间,onload时间,白屏时间等,以及单个页面资源从发送请求到得到响应每个阶段的性能参数。对我们比较有用的页面性能数据大概有以下几种。这些参数由上面的performance.timing属性的不同组成。它是一个精确到毫秒的值。计算方法如下:重定向耗时:redirectEnd-redirectStartDNS查询耗时:domainLookupEnd-domainLookupStartTCP连接耗时:connectEnd-connectStartHTTP请求耗时:responseEnd-responseStart解析dom树耗时:domComplete-domInteractive白屏time:responseStart-navigationStartDOMreadytime:domContentLoadedEventEnd-navigationtime:loadEventEnd-navigationStart,即onload回调函数的执行时间。如何优化?重定向优化:重定向分为三种,301(永久重定向)、302(临时重定向)、304(NotModified)。304用于优化缓存,非常有用,前两个尽量避免。每当遇到需要重定向跳转代码的代码时,可以将重定向后的地址直接写到前端html或JS中,可以减少客户端与服务端的通信过程,节省重定向时间。DNS优化:一般来说,前端优化中与DNS相关的有两点:一是减少DNS请求次数,二是进行DNS预取(Prefetching)。典型的DNS解析需要20-120毫秒(移动端会慢一些),减少DNS解析次数是一个很好的优化方法,尽量把各种资源放在一个cdn域名上。DNSPrefetching允许在后台解析具有该属性的域名,无需用户点击链接,域名解析和内容加载是串行的网络操作,因此这种方式可以减少用户的等待时间,提高用户体验。新版浏览器会预取页面上与当前域名(浏览网页的域名)不在同一域的域名,并缓存结果。这是隐式DNS预取。如果要预取页面上没有出现的域,则必须使用显示的DNS预取。下图是DNSPrefetch的方法:Tencent.comTCP请求优化:TCP优化多在服务端,前端能做什么就是尽量减少TCP请求数,也就是减少HTTP请求数。HTTP1.0默认使用短连接,也是TCP短连接,即客户端和服务器每进行一次HTTP操作,就建立一次连接,任务完成后终止连接。在这个过程中,有3次TCP请求握手,4次TCP请求释放。有两种方法可以减少TCP请求。一种是资源合并,将页面中的图片、css、js合并,减少请求量。另一种是使用长链接,使用http1.1,在HTTP响应头中加入Connection:keep-alive。打开网页时,连接不会立即关闭。再次访问这个服务时,会继续使用这个长链接。连接。这大大减少了TCP握手和释放的次数。或者使用Websocket进行通信,整个过程只需要建立一次TCP连接。HTTP请求优化:使用内容分发网络(CDN)并减少请求。使用CDN可以减少网络请求延迟。CDN的域名不能与主站域名相同。这样就可以避免访问CDN时携带主站cookie的问题。对于网络请求,可以使用fetch发送不带cookie的请求,减少http包的大小。您还可以使用本地缓存策略来最大程度地减少重复获取服务器数据。渲染优化:浏览器端的渲染过程,比如大型框架,vue和react,它的模板其实都是在浏览器端渲染的,不是直接出来的html,而是框架里面的相关框架代码去渲染页面,这个渲染过程对首屏损失较大,白屏时间会增加。如果需要的话,可以在服务端渲染整个html,这样就可以直接将整个html输出到我们的浏览器,而不是在浏览器端渲染。另一个问题是,默认情况下,JavaScript执行“阻塞解析器”,当浏览器遇到脚本外部链接标签时,DOM构建将暂停,控制权将交给JavaScript运行时,等待脚本下载完成后执行完成后,继续构建DOM。除非编写额外的代码来延迟它们的执行,否则内联脚本将始终阻塞解析器。我们可以在页面底部添加脚本外部链接,或者使用defer或者async来延迟执行。defer和async的区别在于defer是有序的,代码在html中是按照顺序执行的,而async是无序的,下载完成就执行。或者使用异步编程方式,比如settimeout,或者使用多线程的webworkers,这些都不会阻塞DOM的渲染。资源性能APIperformance.timing记录用于Analyze整体页面性能指标。如果要获取单个资源(如JS、图片)的性能指标,需要使用ResourceTimingAPI。performance.getEntries()方法包含所有静态资源的数组列表;每一项都是请求相关的参数,比如名称、类型、时间等。下图是腾讯网chrome显示的相关资源列表。可以看出,与performance.timing相比:没有DOM相关的属性,新增了四个属性:name、entryType、initiatorType、duration。它们是name的意思:资源的名字,也就是资源的绝对路径。可以通过performance.getEntriesByName(name属性的值)获取该资源加载的具体属性。entryType表示:资源类型“resource”,还有“navigation”、“mark”、“measure”三种类型。initiatorType表示:请求源“link”表示标签,“script”表示