当前位置: 首页 > Web前端 > JavaScript

PerformanceAPI不完全指南

时间:2023-03-26 21:57:29 JavaScript

本教程解释了如何使用PerformanceAPI来记录有关访问您的应用程序的真实用户的统计信息。使用浏览器的DevTools评估Web应用程序性能很有用,但要复制真实世界的使用情况并不容易。因为人们在不同的地方使用不同的设备、浏览器和网络,他们会有不同的体验。PerformanceAPI简介PerformanceAPI使用缓冲区在网页生命周期的特定时刻在对象属性中记录类似DevTool的指标。这些节点包括:页面导航:记录页面加载重定向、连接、握手、DOM事件等。资源加载:记录资源加载,例如图像、CSS、脚本和Ajax调用。RenderingMetrics:记录浏览器渲染信息。自定义:记录任意应用程序处理时间以查找慢速函数。所有API都可以在客户端的JavaScript中使用,包括WebWorkers。您可以通过以下方式检查API支持:if('performance'inwindow){//callPerformanceAPIs}注意:尽管Safari实现了大部分API,但Safari并不支持所有方法。还复制了自定义性能API:Node.js内置的performance_hook模块和Deno性能API(使用它的脚本必须以--allow-hrtime权限运行)。Date()还不够好吗?您可能见过使用Date()函数记录经过时间的示例。例如:conststart=newDate();//...运行代码...constelapsed=newDate()-start;但是,Date()计算仅限于最接近的毫秒,并且基于系统时间。操作系统可以随时更新系统时间。性能API使用独立的高分辨率计时器,可以以毫秒为单位进行记录。它还提供原本不会记录的指标,例如重定向和DNS查找时间。记录性能指标如果您可以在某处记录它们,那么在客户端代码中记录性能指标将非常有用。您可以使用Fetch/XMLHttpRequest请求,或者使用BeaconAPI将统计数据发送到服务器进行分析。此外,大多数分析系统都提供类似的事件API来记录时间。例如,GoogleAnalytics的UserTimingsAPI可以通过传递类别'pageload'、变量名称'DOMready'和一个值来记录DOMContentLoaded的时间:constpageload=performance.getEntriesByType('navigation')[0];ga('发送','定时','pageload','DOMready',pageload.domContentLoadedEventStart);此示例使用页面导航计时API,因此从这里开始。页面导航时间在快速连接上测试您的网站,并不代表用户体验。浏览器的DevTools中的NetWork选项卡允许您限制速度,但它无法模拟不良或间歇性信号。NavigationTimingAPI将各个PerformanceNavigationTiming对象放入性能缓冲区。它包含有关重定向、加载时间、文件大小、DOM事件等的信息。通过运行以下代码访问该对象:constpagePerf=performance.getEntriesByType('navigation');或将页面URL(window.location)传递给getEntriesByName()方法以访问对象:constpagePerf=performance.getEntriesByName(window.location);两者都返回一个数组,该数组包含具有只读属性的对象的单个元素。例如:[{name:"",initiatorType:"navigation",entryType:"navigation",initiatorType:"navigation",type:"navigate",nextHopProtocol:"h2",startTime:0...}]该对象包含资源标识属性:属性描述名称资源URLentryType性能类型——“navigation”代表一个页面,“resource”代表一个资源initiatorType开始下载资源——“navigation”代表一个页面nextHopProtocolnetworkAn协议serverTimingPerformanceServerTiming对象数组注意:performanceServerTiming的名称、描述、持续时间等指标由服务器响应写入HTTPServer-Timing头中。该对象包含一个资源时间属性,以毫秒为单位,相对于页面加载开始时间。通常,时间会按如下顺序显示:属性描述startTime开始抓取页面的时间戳,从0开始workerStartServiceWorker启动前的时间戳节后fetchStart资源获取开始前的时间戳domainLookupStartDNS查询前的时间戳domainLookupEndDNS查询后的时间戳connectStart建立服务器连接前的时间戳connectEnd建立服务器连接后的时间戳secureConnectionStartSSL握手前的时间戳请求前的时间戳responseEnd收到数据最后一个字节后的时间戳duration从startTime到responseEnd经过的时间该对象包含下载字节数Size属性:描述transferSize资源大小的属性,包括header和bodyencodedBodySize解压前的资源体大小decodedBodySize解压后的资源体大小最后,该对象包括进一步的导航和DOM事件属性(Safari中不可用):属性描述类型“navigate”、“reload”、“back_forward”或“prerender”redirectCount重定向次数unloadEventStart上一个文档卸载事件之前的时间戳unloadEventEnd上一个文档卸载事件之后的时间戳domInteractive当HTML解析和DOM构建完成时handlerdomCompleteDOMbuild和DOMContentLoaded事件完成后的时间戳loadEventStart页面加载事件前的时间戳完全加载如下:'performance'inwindow&&window.addEventListener('load',()=>{constpagePerf=performance.getEntriesByName(window.location)[0],pageDownload=pagePerf.duration,pageDomComplete=pagePerf.domComplete;});页面资源时间当页面加载图像、字体、CSS文件和JavaScript文件等资产时,ResourceTimingAPI将PerformanceResourceTiming对象放入性能缓冲区,可以这样运行:constresPerf=performance.getEntriesByType('资源');这将返回资源时间对象数组,这些属性与上面显示的页面时间相同,但没有导航和DOM事件信息。以下是返回结果的示例:[{name:"",entryType:"resource",initiatorType:"link",fetchStart:150,duration:300...},{name:"",entryType:"resource",initiatorType:"script",fetchStart:302,duration:112...},...]单一资源可以将资源URL传给.getEntriesByName()方法进行测试:constresourceTime=performance.getEntriesByName('');这将返回一个单元素数组:[{name:"",entryType:"resource",initiatorType:"link",fetchStart:150,duration:300...}]API可用于报告加载时间和每个CSS文件解压后的大小://CSS文件数组、加载时间和文件大小constcss=performance.getEntriesByType('resource').filter(r=>r.initiatorType==='link'&&r.name.includes('.css')).map(r=>({name:r.name,load:r.duration+'ms',size:r.decodedBodySize+'bytes'}));CSS数组现在包含每个CSS文件的对象,例如:[{name:"",load:"155ms",size:"14304bytes"},{name:"",load:"203ms",size:"5696bytes"}]注:load的大小为0,表示资源已经缓存。至少150个资源指标对象将被记录到性能缓冲区。您可以使用.setResourceTimingBufferSize(N)方法定义指定的数字。例如://记录500个资源performance.setResourceTimingBufferSize(500);可以使用.clearResourceTimings()方法清除现有指标。BrowserPaintTimeFirstContentfulPaint(FCP)测量用户导航到您的页面后呈现内容所需的时间。Chrome的DevTools的Lighthouse选项卡显示了这个指标。Google认为FCP时间小于两秒是好的,并且您的页面呈现速度将超过所有页面的75%。PaintTimingAPI在出现以下两种情况时,会向性能缓冲区中推送两条记录,即两个PerformancePaintTiming对象:first-paint发生:浏览器绘制第一个像素,first-contentful-paint发生:浏览器绘制了第一个DOM元素运行以下代码时,这两个对象将作为数组返回:constpaintPerf=performance.getEntriesByType('paint');返回结果示例:[{"name":"first-paint","entryType":"paint","startTime":125},{"name":"first-contentful-paint","entryType":"paint","startTime":127}]startTime是相对于初始页面加载时间。用户计时性能API可用于为您自己的应用程序功能计时。所有用户时间方法都可以在客户端使用JavaScript、WebWorkers、Deno和Node.js获得。请注意,Node.js脚本必须加载性能挂钩(perf_hooks)模块。**CommonJSrequire语法:const{performance}=require('perf_hooks');或ESMimport语法:从'perf_hooks'导入{performance};最简单的选项是[performance.now()](),它从程序生命周期开始时返回高精度时间戳。您可以将performance.now()用作简单的计时器。例如:conststart=performance.now();//...运行代码...constelapsed=performance.now()-start;请注意,非标准timeOrigin属性返回时间戳。适用于Node.js和浏览器JavaScript,但不适用于IE和Safari。performance.now()在管理多个计时器时很快变得不切实际。.mark()方法将一个名为PerformanceMark对象的对象添加到性能缓冲区。例如:performance.mark('script:start');performance.mark('p1:start');//...运行进程1...performance.mark('p1:end');performance.mark('p2:start');//...运行进程2...performance.mark('p2:end');performance.mark('script:end');以下代码返回一个标记对象数组:constmarks=performance.getEntriesByType('mark');数组中的对象具有entryType、name和startTime属性:[{entryType:"mark",name:"script:start",startTime:100},{entryType:"mark",name:"p1:start",startTime:200},{entryType:"mark",name:"p1:end",startTime:300},...]两个标记之间的时间可以用.measure()方法来计算。它传递了一个测量名称、开始标记名称(或空值)和结束标记名称(或空值):performance.measure('p1','p1:start','p1:end');performance.measure('script',null,'script:end');每次调用都会将具有计算持续时间的PerformanceMeasure对象推送到性能缓冲区。可以通过运行访问测量数组:constmeasures=performance.getEntriesByType('measure');返回示例:[{entryType:"measure",name:"p1",startTime:200,duration:100},{entryType:"measure",name:"script",startTime:0,duration:500}]标记或可以使用.getEntriesByName()方法按名称检索测量对象:performance.getEntriesByName('p1');其他方法:.getEntries():返回所有性能条目的数组。[.clearMarks([name])](https://developer.mozilla.org...):Clearthemarkwiththespecifiedname(清除所有标记而不指定名称)。[.clearMeasures([name])](https://developer.mozilla.org...):Clearthemeasurementwiththespecifiedname(清除所有没有指定名称的测量)。PerformanceObserver可以监视缓冲区的变化,并在指定对象出现时执行函数。观察者函数定义了两个参数:list:观察者入口observer(可选):观察者对象函数performanceHandler(list,observer){list.getEntries().forEach(entry=>{console.log(`name:${entry.name}`);console.log(`type:${entry.type}`);console.log(`duration:${entry.duration}`);//其他代码,例如//通过一个Ajax请求});}函数被传递一个新的PerformanceObserver对象。.observe()方法设置可观察的条目类型(通常是标记、度量或资源):letobserver=newPerformanceObserver(performanceHandler);observer.observe({entryTypes:['mark','measure']});每当将新标记或测量对象推送到性能缓冲区时,performanceHandler()函数就会运行。总结PerformanceAPI提供了一种方法来测量网站和应用程序在不同位置的人们通过一系列连接使用的实际设备上的速度。它使每个人都可以轻松整理类似DevTool的指标并识别潜在的瓶颈。以上就是本文的全部内容。如果对你有帮助,请点赞、收藏、转发~