欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS前端性能指標(biāo)定位FMP使用詳解

 更新時(shí)間:2023年01月10日 16:17:05   作者:木羽ZW  
這篇文章主要為大家介紹了JS前端性能指標(biāo)定位FMP使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

什么是FMP?

可能大家對(duì)「白屏?xí)r間」這個(gè)名詞并不陌生,他是「刀耕火種」年代,我們收集的頁(yè)面性能指標(biāo)之一,隨著前端工程的復(fù)雜化,白屏?xí)r間已經(jīng)沒(méi)有什么實(shí)質(zhì)性的意義了,取而代之的就是 FMP。

先來(lái)介紹幾個(gè)與之相關(guān)的名詞。

  • FP(First Paint):首次繪制,標(biāo)記瀏覽器渲染任何在視覺(jué)上不同于導(dǎo)航前屏幕內(nèi)容的時(shí)間點(diǎn)
  • FCP(First Contentful Paint):首次內(nèi)容繪制,標(biāo)記的是瀏覽器渲染第一針內(nèi)容 DOM 的時(shí)間點(diǎn),該內(nèi)容可能是文本、圖像、SVG 或者 <canvas> 等元素
  • FMP(First Meaning Paint):首次有效繪制,標(biāo)記主角元素渲染完成的時(shí)間點(diǎn),主角元素可以是視頻網(wǎng)站的視頻控件,內(nèi)容網(wǎng)站的頁(yè)面框架也可以是資源網(wǎng)站的頭圖等。

相對(duì)于 FP 和 FCP,F(xiàn)MP 是我們前端最常關(guān)注的重要性能指標(biāo),Google 定義它為「是否有用?」的時(shí)間點(diǎn)。然而,「是否有用?」是很難以通用方式界定的,因此,至今依然沒(méi)有標(biāo)準(zhǔn)的 API 輸出。

社區(qū)中常有這么幾種方式進(jìn)行「相對(duì)準(zhǔn)確」的計(jì)算 FMP,所謂相對(duì)準(zhǔn)確,是相對(duì)于實(shí)際項(xiàng)目而言。

  • 主動(dòng)上報(bào):開(kāi)發(fā)者在相應(yīng)頁(yè)面的「Meaning」位置上報(bào)時(shí)間
  • 權(quán)重計(jì)算:根據(jù)頁(yè)面元素,計(jì)算權(quán)重最高的元素渲染時(shí)間
  • 趨勢(shì)計(jì)算:在 render 期間,根據(jù) dom 的變化趨勢(shì)推算 FMP 值

本文將著重介紹第二種方式。

權(quán)重定位

所謂權(quán)重,即,將頁(yè)面的元素以約定的「權(quán)重比」遍歷出「權(quán)重值」最大的某一個(gè)或一組 DOM,然后以其「裝載時(shí)間點(diǎn)」或「加載結(jié)束點(diǎn)」作為 FMP 的映射。

權(quán)重計(jì)算

節(jié)點(diǎn)標(biāo)記

想要對(duì) DOM 節(jié)點(diǎn)進(jìn)行階段性標(biāo)記,就得有監(jiān)聽(tīng) DOM 變化的能力,慶幸的是,HTML5 賦予了我們這個(gè)能力。

MutationObserver,Mutation Events功能的替代品,是DOM3 Events規(guī)范的一部分。他可以在指定的 DOM 發(fā)生變化時(shí)執(zhí)行回調(diào)。

MutationObserver 有三個(gè)方法

  • disconnect() 阻止 MutationObserver 實(shí)例繼續(xù)接收的通知,直到再次調(diào)用其observe()方法,該觀察者對(duì)象包含的回調(diào)函數(shù)都不會(huì)再被調(diào)用。
  • observe() 配置MutationObserver在DOM更改匹配給定選項(xiàng)時(shí),通過(guò)其回調(diào)函數(shù)開(kāi)始接收通知。
  • takeRecords() 從MutationObserver的通知隊(duì)列中刪除所有待處理的通知,并將它們返回到MutationRecord對(duì)象的新Array中。
global.mo = new MutationObserver(() => { 
    /* callback: DOM 節(jié)點(diǎn)設(shè)置階段性標(biāo)記 */
});
/**
 * mutationObserver.observe(target[, options])
 * target - 需要觀察變化的 DOM Node。
 * options - MutationObserverInit 對(duì)象,配置需要觀察的變化項(xiàng)。
 * 更多 options 的介紹請(qǐng)參考 https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserverInit#%E5%B1%9E%E6%80%A7
 **/
global.mo.observe(document, {
  childList: true,  // 監(jiān)聽(tīng)子節(jié)點(diǎn)變化(如果subtree為true,則包含子孫節(jié)點(diǎn))
  subtree: true // 整個(gè)子樹(shù)的所有節(jié)點(diǎn)
});

下圖粗濾的解析了正常單頁(yè)面的渲染過(guò)程

  • 預(yù)備階段:導(dǎo)航階段,處在連接相應(yīng)的過(guò)程
  • 階段一:首字節(jié)渲染階段,也是FCP,DOM 樹(shù)的第一次有效變化
  • 階段二:基本框架渲染完成
  • 階段三:獲取到數(shù)據(jù),渲染到視圖上
  • 階段四:圖片加載完成,加載過(guò)程不被標(biāo)記

實(shí)際上在第一、第三階段之間還存在著大量的 DOM 變化,Mutation Observer 事件的觸發(fā)并不是同步的,而是異步觸發(fā)的,也就是說(shuō),等到當(dāng)前「階段」所有 DOM 操作都結(jié)束才觸發(fā)。

Mutation Observer 有以下特點(diǎn)

  • 它等待所有腳本任務(wù)完成后,才會(huì)運(yùn)行(即異步觸發(fā)方式)。
  • 它把 DOM 變動(dòng)記錄封裝成一個(gè)數(shù)組進(jìn)行處理,而不是一條條個(gè)別處理 DOM 變動(dòng)。
  • 它既可以觀察 DOM 的所有類(lèi)型變動(dòng),也可以指定只觀察某一類(lèi)變動(dòng)。

load 事件觸發(fā)后,各個(gè)階段的 tag 已經(jīng)被打到標(biāo)簽上了

此處以『_ti』昨晚標(biāo)記 key。

在打標(biāo)記的同時(shí),需要記錄下當(dāng)前的時(shí)間節(jié)點(diǎn),備用

// 偽代碼
function callback() {
    global.timeStack[++_ti] = performance.now(); // 記時(shí)間
    doTag(_ti); // 打標(biāo)記
}

標(biāo)記打完后就等 load 的那一刻進(jìn)行計(jì)算反推了。

計(jì)算權(quán)重值

一般來(lái)說(shuō)

  • 視圖占比越大的元素越有可能是主角元素
  • 視頻比圖片更可能是主角元素
  • svgcanvas 也很重要
  • 其他元素都可以按普通 dom 計(jì)算了
  • 背景圖片視情況而定,可記可不記

第一步:簡(jiǎn)單粗暴,按大小計(jì)算

// 偽代碼
function weightCompute(node){
    let {
        width,
        height,
        left,
        top
    } = node.getBoundingClientRect();
    // 排除視圖外的元素
    if(isOutside(width, height, left, top)){
        return 0;
    }
    let wts = TAG_WEIGHT_MAP[node.tagName]; // 約定好的權(quán)重比
    let weight = width * height * wts; // 直接乘,或者更細(xì)粒度的計(jì)算 wts(width, height, wts)
    return {
        weight, 
        wts, 
        tagName: node.tagName, 
        ti: node.getAttribute("_ti"),
        node
    };
}

第二步:根據(jù)權(quán)重值推導(dǎo)主角元素

在我們的約定權(quán)重算法下,權(quán)重最大的元素即為我們推到的主角元素。

// 偽代碼
function getCoreNode(node){
    let list = nodeTraversal(node); // 遞歸計(jì)算每個(gè)標(biāo)記節(jié)點(diǎn)的權(quán)重值
    return getNodeWithMaxWeight(list); // weight 最大的元素
}

第三步:根據(jù)元素類(lèi)型取時(shí)間

不同的元素獲取時(shí)間的方式并不相同

  • 普通元素:按標(biāo)記點(diǎn)時(shí)間計(jì)算
  • 圖片和視頻:按資源相應(yīng)結(jié)束時(shí)間計(jì)算
  • 帶背景元素:可以以背景資源相應(yīng)結(jié)束時(shí)間計(jì)算,也可以按普通元素計(jì)算
// 偽代碼
function getFMP(){
    let coreObj = getCoreNode(document.body),
        fmp = -1;
    let {
        tagName,
        ti,
        node
    } = coreObj;
    switch(tagName){
        case 'IMG':
        case 'VIDEO':
            let source = node.src;
            let { responseEnd } = performance.getEntries().find(item => item.name === source);
            fmp = responseEnd || -1;
            break;
        default:
            if(node.style.backgroundImage){
                // 普通元素的背景處理
            }else{
               fmp = global.timeStack[+ti]; 
            }
    }
    return fmp;
}

回歸驗(yàn)證

以我們的 demo 頁(yè)為例,類(lèi)似的電商網(wǎng)站,我們希望拿到「階段二」或「階段三」的時(shí)間點(diǎn)作為我們的 FMP 值。

因?yàn)槲覀儾⒉幌M钢鹘窃亍沟谋尘盎蛘摺笀D片主角元素」的相應(yīng)時(shí)間算在 FMP 的值內(nèi),所以,我們將「圖片」「視頻」等資源元素降級(jí)成普通元素計(jì)算。

在 Chrome [ Disable cache / Fast 3G ] 條件下我們進(jìn)行模擬驗(yàn)證。

計(jì)算得到的 FMP 值為 4730.7ms,Chrome Performance 監(jiān)控的值在 4950ms 左右,誤差在 200ms 左右。

如果將限速放開(kāi),F(xiàn)MP 的取值將更接近我們希望的「First Meaning Paint」。

以上就是JS前端性能指標(biāo)定位FMP使用詳解的詳細(xì)內(nèi)容,更多關(guān)于JS前端性能指標(biāo)定位FMP的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論