今天來給你們介紹下前端監控中一個特定指標的獲取算法,有人會問,爲啥就單單講一個指標?這是由於,目前大部分的指標,好比白屏時間,dom加載時間等等,都能經過現代瀏覽器提供的各類api去進行較爲精確的獲取,而今天講的這個指標,以往獲取他的方式只能是經過邏輯埋點去獲取它的值,所以在作一些前端監控時,須要根據業務須要去改變頁面對這個值的埋點方式,會比較繁瑣,恰巧最近剛恰好在作一些前端監控相關的項目,遇到這個問題時就在想,能不能經過一種無須埋點的方式,將這個值給獲取到?倒騰了一段時間,終於把算法弄出來了,今天就來給你們介紹下————FMP(first meaning paint) 指標的智能獲取算法javascript
解答這個問題以前,咱們先來了解下現代前端監控性能的主要指標統計方法,在2013年以後,標準組織推出了 performance timing api
,以下圖html
這個api統計了瀏覽器從網址開始導航到 window.onload
事件觸發的時間點,好比請求開始的時間點——requestStart
,響應結束的時間點——responseEnd
,經過這些時間點咱們能夠計算出一些對頁面加載質量有指導意見的時長,好比如下幾個:前端
經過這些指標咱們能夠獲得不少有用的web端網頁加載信息,創建對網頁性能概況java
以上的指標能夠對網頁進行數值化的衡量,可是其實這種衡量只能體現一個視角的性能觀點,好比TTFB很快,就能表明用戶可以很快的看到頁面的內容嘛?這個不必定是成立的,所以人們有開始從用戶的視角去分析網頁加載的性能狀況,將用戶看待加載過程,分紅了如下幾個階段:git
而咱們今天討論的FMP(first meaningful paint)
,其實就是回答 is it useful
,加載的內容是否已經足夠,其實這是一個很難被定義的概念。每一個網頁都有本身的特色,只有開發者和產品可以比較肯定哪一個元素加載的時間點屬於FMP
,今天咱們就來討論一下,如何比較智能的去找出頁面那個主要的元素,肯定頁面的FMP
github
首先咱們能夠看看下面的圖: web
useful
的內容,都是含有信息量比較豐富的,好比圖片,視頻,動畫,另外就是佔可視面積較大的,頁面中還存在兩種形態的內容能夠被視爲是
useful
的,一種是單一的塊狀元素,另一種是由多個元素組合而成的大元素,好比視頻元素,banner圖,這種屬於單一的塊狀元素,而像圖片列表,多圖像的組合,這種屬於元素組合 總結一下成爲FMP元素的條件:
前面介紹了FMP
的概念還有成爲FMP
的條件,接下來咱們來看看如何設計FMP
獲取的算法,按照上面的介紹,咱們知道算法分爲如下兩個部分:算法
FMP元素
FMP元素
的加載時間若是有了解過瀏覽器加載原理的同窗都知道,瀏覽器在在獲取到html頁面以後會逐步的對html文檔進行解析,遇到javascript會中止html文檔的解析工做,執行javascript,執行完繼續解析html,直到整個頁面解析完成爲止。頁面除了html文檔中的元素加載,可能在執行javascript的時候,會產生動態的元素片斷加載,通常來講,首屏元素會在這期間加載。所以咱們只須要監控元素的加載和加載的時間點,而後再進行計算。canvas
具體的算法流程以下圖api
相關的代碼連接我已經放在最後面了,下面我會逐步的講解整個算法流程
我把整個流程分爲兩個下面兩個部分:
FMP元素
,計算出最終的FMP
值下面咱們按照步驟來分析
能夠看到首先咱們先執行了firstSnapshot
方法,用於記錄在代碼執行以前加載的元素的時間點
接下來初始化MutationObserver
,開始監聽document
的加載狀況,在發生回調的時候,記錄下當前到performance.timing.fetchStart
的時間間隔,而後對body的元素進行深度遍歷,進行打點,記錄是在哪一次回調的時候記錄的,以下圖
監聽的最後咱們會將在window.onload
的時候去觸發檢查是否中止監聽的條件,以下圖
LIMIT
,或者發生回調的時間間隔已經超過1s中,咱們認爲頁面已經穩定,中止dom元素加載的監聽,開始進入計算過程 首先前面咱們說了,咱們的元素對於頁面的貢獻是不一樣的,資源加載的元素會對用戶視覺感官的影響比較大,好比圖片,帶背景的元素,視頻等等,所以我設計了一套權重系統,以下:
svg
,img
的權重爲2,canvas
,object
,embed
,video
的權重爲4,其餘的元素爲1, 也就是說,若是一個圖片面積爲1/2首屏面積,其實他的影響力會和普通元素佔滿首屏的影響力同樣 接着咱們回到代碼,咱們首先會對整個頁面進行深度優先遍歷搜索,而後對每個元素進行進行分數計算,以下圖
element.getBoundingClientRect
獲取了元素的位置和大小,而後經過計算"width * height * weight * 元素在viewport的面積佔比"
的乘積,肯定元素的最終得分,而後將改元素的子元素得分之和與其得分進行比較,去較大值,記錄得分元素集 FMP
元素,計算最終FMP
時間經過上面的步驟咱們獲取到了一個集合,這個集合是"可視區域內得分最高的元素的集合",咱們會對這個集合的得分取均值,而後過濾出在平均分之上的元素集合,而後進行時間計算
能夠看到分爲兩種狀況去處理:
weight
爲1的普通元素,那麼咱們會經過元素上面的標記,去查詢以前保存的時間集合,獲得這個元素的加載時間點weight
不爲1的元素,那麼其實就存在資源加載狀況,元素的加載時間實際上是資源加載的時間,咱們經過performance.getEntries
去獲取對應資源的加載時間,獲取元素的加載速度最後去全部元素最大的加載時間值,做爲頁面加載的FMP
時間
以上就是整個算法的比較具體的流程,可能有人會說,這個東西算出來的就是準確的麼?這個算法實際上是按照特徵分析,特定的規則總結出來的算法, 整體來講仍是會比較準確,固然web頁面的佈局若是比較奇特,多是會存在一些誤差的狀況。也但願你們可以一塊兒來豐富這個東西,爲FMP
這個計算方法提出本身的建議 附上代碼 連接