目录html
主要用于测试html的页面性能采集。介绍了传统的性能指标和采集方式,
此外介绍了Google正在力推的以用户为中心的性能指标,以及相应的采集方式。git
目前业界经常使用的指标就是:白屏
、首屏
、domready
和pageloaded
四个指标,在usual-index.html中,
咱们经过performance API获取到响应的指标值。github
通常是认为DOM Tree构建时,解析到或的时候,咱们认为是白屏结束的时间点。
咱们能够在这个时候使用performace.mark进行打点标记,最后能够经过performance的
entry.startTime来获取白屏时间,其中entry.startTime是相对于performance.timing.navigationStart的时间。web
<head> ... <script> // 一般在head标签尾部时,打个标记,这个一般会视为白屏时间 performance.mark("first paint time"); </script> </head> <body> ... <script> // get the first paint time const fp = Math.ceil(performance.getEntriesByName('first paint time')[0].startTime); </script> </body>
通常是首屏中的图片加载完毕的时候,咱们认为是首屏结束的时间点。咱们能够对首屏中的image作onload事件绑定,
performace.mark进行打点标记,不过打点前先进行performance.clearMarks清除操做,以获取到多张图片最后加载完毕的时间。npm
<body> <div class="app-container"> <img src="a.png" onload="heroImageLoaded()"> <img src="b.png" onload="heroImageLoaded()"> <img src="c.png" onload="heroImageLoaded()"> </div> <script> // 根据首屏中的核心元素肯定首屏时间 performance.clearMarks("hero img displayed"); performance.mark("hero img displayed"); function heroImageLoaded() { performance.clearMarks("hero img displayed"); performance.mark("hero img displayed"); } </script> ... ... <script> // get the first screen loaded time const fmp = Math.ceil(performance.getEntriesByName('hero img displayed')[0].startTime); </script> </body>
这两个指标有相应的事件监听,即document的DOMContentLoaded和window.onload,直接在事件的回调中使用performance打点便可。promise
<script> document.addEventListener('DOMContentLoaded', ()=> { performance.mark("dom ready"); }); window.onload = ()=> { performance.mark("page loaded"); // get the domReady time const domReady = Math.ceil(performance.getEntriesByName('dom ready')[0].startTime); // get the page loaded time const pageLoad = Math.ceil(performance.getEntriesByName('page loaded')[0].startTime); } </script>
这个是Google力推的指标,主要从4个视觉反馈阶段来描述页面性能。浏览器
视觉反馈 | 页面状态 | 性能指标 |
---|---|---|
是否发生? | 导航是否成功启动?服务器是否有响应? | 首次绘制 (FP)/首次内容绘制 (FCP) |
是否有用? | 是否已渲染能够与用户互动的足够内容? | 首次有效绘制 (FMP)/主角元素计时 |
是否可用? | 用户能够与页面交互,仍是页面仍在忙于加载? | 可交互时间 (TTI) |
是否使人愉快? | 交互是否顺畅而天然,没有滞后和卡顿? | 耗时较长的任务(在技术上不存在耗时较长的任务) |
对应的指标以下图所示:
此外,Google也提供了一些新的API,来获取相应的指标值。服务器
PerformanceObserver
为咱们提供的新功能是,可以在性能事件发生时订阅这些事件,并以异步方式响应事件。app
let perfomanceMetrics = {}; const observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { // `entry` is a PerformanceEntry instance. // `name` will be either 'first-paint' or 'first-contentful-paint'. const metricName = entry.name; const time = Math.round(entry.startTime + entry.duration); if (metricName === 'first-paint') { perfomanceMetrics.fp = time; } if (metricName === 'first-contentful-paint') { perfomanceMetrics.fcp = time; } } }); // Start observing the entry types you care about. observer.observe({entryTypes: ['paint']});
目前尚无标准化的 FMP 定义,通常来讲,是将 FMP 视为主角元素呈如今屏幕上的时刻。
这个的计算方法就同上面介绍的首屏指标获取,只是首屏肯定的是首页中的图片,而 FMP 肯定的是核心元素。dom
TTI 主要是经过跟踪耗时较长的任务来肯定,设置PerformanceObserver
观察类型为 longtask 的条目,
而后能够根据耗时较长的条目的startTime和duration,来大体确认页面处于idle的时间,从而肯定 TTI 指标。
Google但愿将 TTI 指标标准化,并经过 PerformanceObserver 在浏览器中公开,但目前并不支持。
目前只能经过一个 polyfill,检测目前的 TTI,适用于全部支持 Long Tasks API 的浏览器。
该 polyfill 公开 getFirstConsistentlyInteractive() 方法,后者返回使用 TTI 值进行解析的 promise。
用法以下所示:
<head> <script> // collect the longtask if (PerformanceLongTaskTiming) { window.__tti = {e: []}; const observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { // observe the longtask to get the time to interactive (TTI) if (entry.entryType === 'longtask') { window.__tti.e.concat(entry); } } }); observer.observe({entryTypes: ['longtask']}); } </script> </head>
import ttiPolyfill from './path/to/tti-polyfill.js'; ttiPolyfill.getFirstConsistentlyInteractive().then((tti) => { ... });
这个同TTI的第一步,设置PerformanceObserver,并指定监控类型为longtask,
获取到的entry包含提供方属性
,有助于追查致使出现耗时较长任务的代码。
https://github.com/huangwenming/learning-notes/tree/master/html-relevant/performance
http://www.alloyteam.com/2015/09/explore-performance/