前端頁面性能指標與采集方式


主要用於測試html的頁面性能采集。介紹了傳統的性能指標和采集方式,
此外介紹了Google正在力推的以用戶為中心的性能指標,以及相應的采集方式。

性能指標

目前業界常用的指標就是:白屏首屏domreadypageloaded四個指標,在usual-index.html中,
我們通過performance API獲取到響應的指標值。

  • 白屏

一般是認為DOM Tree構建時,解析到或的時候,我們認為是白屏結束的時間點。
我們可以在這個時候使用performace.mark進行打點標記,最后可以通過performance的
entry.startTime來獲取白屏時間,其中entry.startTime是相對於performance.timing.navigationStart的時間。

<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清除操作,以獲取到多張圖片最后加載完畢的時間。

<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>
  • domready與pageloaded

這兩個指標有相應的事件監聽,即document的DOMContentLoaded和window.onload,直接在事件的回調中使用performance打點即可。

<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)
是否令人愉快? 交互是否順暢而自然,沒有滯后和卡頓? 耗時較長的任務(在技術上不存在耗時較長的任務)

對應的指標如下圖所示:
image
此外,Google也提供了一些新的API,來獲取相應的指標值。

  • 首次繪制 (FP)/首次內容繪制 (FCP)

PerformanceObserver 為我們提供的新功能是,能夠在性能事件發生時訂閱這些事件,並以異步方式響應事件。

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 視為主角元素呈現在屏幕上的時刻。
這個的計算方法就同上面介紹的首屏指標獲取,只是首屏確定的是首頁中的圖片,而 FMP 確定的是核心元素。

  • 可交互時間 (TTI)

TTI 主要是通過跟蹤耗時較長的任務來確定,設置PerformanceObserver觀察類型為 longtask 的條目,
然后可以根據耗時較長的條目的startTime和duration,來大致確認頁面處於idle的時間,從而確定 TTI 指標。
Google希望將 TTI 指標標准化,並通過 PerformanceObserver 在瀏覽器中公開,但目前並不支持。
目前只能通過一個 polyfill,檢測目前的 TTI,適用於所有支持 Long Tasks API 的瀏覽器。
該 polyfill 公開 getFirstConsistentlyInteractive() 方法,后者返回使用 TTI 值進行解析的 promise。
用法如下所示:

  1. 首先是在中設置PerformanceObserver,並指定監控類型為longtask。
<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>
  1. 然后引入tti-polyfill.js(可通過npm包獲取),獲取到tti的值。
import ttiPolyfill from './path/to/tti-polyfill.js';

ttiPolyfill.getFirstConsistentlyInteractive().then((tti) => {
  ...
});
  • 耗時較長的任務

這個同TTI的第一步,設置PerformanceObserver,並指定監控類型為longtask,
獲取到的entry包含提供方屬性,有助於追查導致出現耗時較長任務的代碼。

示例demo

https://github.com/huangwenming/learning-notes/tree/master/html-relevant/performance

參考資料

http://www.alloyteam.com/2015/09/explore-performance/

https://speedcurve.com/blog/user-timing-and-custom-metrics/

https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#user-centric_performance_metrics

https://github.com/GoogleChromeLabs/tti-polyfill


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM