成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

關(guān)于首屏?xí)r間采集自動(dòng)化的解決方案

Rindia / 2474人閱讀

摘要:關(guān)于首屏首屏?xí)r間是指從轉(zhuǎn)向該頁(yè)面到屏幕中該頁(yè)面所有內(nèi)容都可見(jiàn)時(shí)的時(shí)間。如在事件處理函數(shù)中,計(jì)算高度,如果大于屏幕高度則意味著首屏的結(jié)構(gòu)已渲染完畢,開(kāi)始計(jì)算首屏?xí)r間。

關(guān)于首屏

首屏?xí)r間是指從轉(zhuǎn)向該頁(yè)面到屏幕中該頁(yè)面所有內(nèi)容都可見(jiàn)時(shí)的時(shí)間。已經(jīng)有太多的關(guān)于首屏?xí)r間的計(jì)算,在本文中并不重復(fù)闡述這些已經(jīng)被提出或者實(shí)現(xiàn)的方案,而旨在探索與討論更多的首屏自動(dòng)化采集方案,擴(kuò)大思考范圍,你我思想之間互相碰撞往往可以激起更多的稀奇古怪的解決方案,這也正是我寫(xiě)這篇文章的目的。

通過(guò)瀏覽器調(diào)試工具,我們可以清晰的看出頁(yè)面資源加載時(shí)序圖:

先是html頁(yè)面加載,token進(jìn)行詞法、語(yǔ)法解析后開(kāi)始加載靜態(tài)資源并執(zhí)行相關(guān)腳本,開(kāi)始構(gòu)建DOM樹(shù)、render樹(shù)和CSSOM數(shù),最后加載圖片,用戶(hù)看到完整的網(wǎng)頁(yè)。

雖然瀏覽器有著各自的優(yōu)化的解決方案,但是大多數(shù)情況下圖片往往是最后加載完畢,這不僅僅是由于圖片的大小相對(duì)較大,而且圖片的加載與否與DOM結(jié)構(gòu)有著很大的關(guān)系。DOM是否構(gòu)建完畢,render樹(shù)中是否渲染以及其他的圖片加載策略有關(guān)系可能都會(huì)影響圖片加載時(shí)序。因此在首屏?xí)r間的計(jì)算中,我們是以最終首屏圖片的加載時(shí)間為節(jié)點(diǎn)計(jì)算的。

首屏計(jì)算 原則1 首屏計(jì)算模塊不應(yīng)該耦合業(yè)務(wù)線(xiàn)

一般而言,首屏計(jì)算作為一個(gè)抽離出的js腳本多帶帶引用,這個(gè)模塊盡量不暴露API給開(kāi)發(fā)者使用,所有的采集端任務(wù)都由該模塊完成。這句話(huà)可能聽(tīng)起來(lái)像一句廢話(huà),但還是有很多情況可能需要業(yè)務(wù)人員來(lái)進(jìn)行首屏渲染時(shí)間的判斷的,下面將針對(duì)這個(gè)情形舉一個(gè)實(shí)際的場(chǎng)景:

隨著MVVM模式的興起,前端異步渲染逐漸流行起來(lái),前端編碼逐漸由面向jQuery編程轉(zhuǎn)向?yàn)槊嫦騐ue編程??墒鞘褂肰ue編寫(xiě)的業(yè)務(wù)代碼在本地打包后僅僅是一個(gè)bundle,此時(shí)的HTML文件中只是一個(gè)

的占位符而已,那么首屏?xí)r間計(jì)算模塊該如何準(zhǔn)確的計(jì)算首屏?xí)r間呢?因此首屏?xí)r間計(jì)算模塊必須知道首屏的DOM結(jié)構(gòu)渲染完畢的時(shí)間節(jié)點(diǎn),在這個(gè)節(jié)點(diǎn)時(shí)刻進(jìn)行計(jì)算首屏范圍內(nèi)的圖片加載時(shí)間。 可是如何獲取首屏DOM結(jié)構(gòu)渲染完畢的時(shí)間節(jié)點(diǎn)呢?這就需要業(yè)務(wù)開(kāi)發(fā)人員制定。在更新vue實(shí)例的data屬性后,通知首屏計(jì)算模塊此時(shí)DOM接口已渲染完畢,開(kāi)始計(jì)算首屏?xí)r間。

MVVM開(kāi)發(fā)模式下,首屏?xí)r間的計(jì)算已經(jīng)耦合了業(yè)務(wù)代碼,雖然可以在保證首屏?xí)r間的準(zhǔn)確性,但卻給開(kāi)發(fā)者帶來(lái)了一些可觀(guān)判斷邏輯,而這些判斷往往會(huì)困擾新入職的同志們,因此我們的目標(biāo)之一就是解決需要手動(dòng)打點(diǎn)進(jìn)行首屏?xí)r間計(jì)算的現(xiàn)狀。

原則2 性能與準(zhǔn)確性的權(quán)衡

業(yè)界有個(gè)通過(guò)canvas截屏并通過(guò)輪詢(xún)對(duì)比不同時(shí)間點(diǎn)截屏圖片之間某幾個(gè)隨機(jī)像素點(diǎn),從而判斷首屏是否加載完畢。這種方式雖然科學(xué),但是估計(jì)沒(méi)有幾個(gè)公司會(huì)采用這種方案。通過(guò)canvas截屏這個(gè)操作對(duì)硬件的要求可能就比較高,而且需要進(jìn)行額外的像素運(yùn)算,因此性能肯定很差。其實(shí)這種場(chǎng)景在工程領(lǐng)域經(jīng)常出現(xiàn),工程不同于科學(xué)那般嚴(yán)謹(jǐn),我們只需要找到給定條件的最優(yōu)解即可,做工程也就是在做trade off。因此這種對(duì)比方案我們也必須摒棄。

實(shí)現(xiàn)

再次強(qiáng)調(diào),由開(kāi)發(fā)者打點(diǎn)首屏DOM渲染完畢進(jìn)行首屏?xí)r間計(jì)算的方式是相對(duì)準(zhǔn)確的方式,因此我們后續(xù)討論的自動(dòng)化計(jì)算首屏?xí)r間的準(zhǔn)確性都是基于此標(biāo)準(zhǔn)進(jìn)行對(duì)比說(shuō)明,因?yàn)樽詣?dòng)化計(jì)算肯定是沒(méi)有人工干預(yù)準(zhǔn)確的,這一點(diǎn)毫無(wú)疑問(wèn)。

輪訓(xùn)采集大法

仍然是輪訓(xùn),不同的是在每次輪詢(xún)中執(zhí)行一些操作:

獲取首屏的所有圖片(包括IMG標(biāo)簽與css相關(guān)屬性)

綁定首屏圖片的onload和onerror事件,每次輪詢(xún)不會(huì)重復(fù)綁定已綁定的圖片

相同圖片不需重復(fù)綁定事件偵聽(tīng),否則會(huì)與 2 中的每次輪詢(xún)混淆

圖片的事件處理函數(shù)執(zhí)行打點(diǎn)信息并統(tǒng)計(jì)圖片加載狀態(tài),同時(shí)比對(duì)時(shí)間戳得到最遲加載的時(shí)間

具體的實(shí)現(xiàn)中,需要特別注意首屏出現(xiàn)的相同圖片的情況。筆者起初在獲取首屏圖片中簡(jiǎn)單計(jì)算圖片的url數(shù)組,存儲(chǔ)重復(fù)圖片的個(gè)數(shù),并且與該圖片的加載狀態(tài)綁定在一起。如首屏中出現(xiàn)了3張相同的圖片,那么在該圖片onload或onerror中對(duì)已加載圖片的數(shù)量做 加3 處理,否則導(dǎo)致最終的 已加載圖片總數(shù) 與 首屏圖片總數(shù) 不相等的情況發(fā)生。這種實(shí)現(xiàn)導(dǎo)致邏輯非常的差,且實(shí)現(xiàn)復(fù)雜。后通過(guò)存儲(chǔ)圖片所在的DOM對(duì)象數(shù)組實(shí)現(xiàn)更為簡(jiǎn)單的圖片狀態(tài)判斷,更加已讀。

偽代碼如下:

// totalCounter為輪詢(xún)的總時(shí)間
// DemandCounter是規(guī)定的輪詢(xún)總時(shí)間,為3000ms
// imgsLoadedCount則為首屏已加載的圖片數(shù)量
// lastImageLoadedStamp為最后加載的圖片時(shí)間戳
function checkFirstScreenDomReady(){
    if(totalCounter >= DemandCounter){
        // ...
        var stamps = Object.keys(pools),
        len = stamps.length,
        i = 0,
        it; 
        finalImgCount = pools[stamps[len - 1]].imgLen; 
        pollEnd = true;

        for(;i= finalImgCount){
                self.onRecord = true;
                _perfQueue._firstScreenLoadEnd = lastImageLoadedStamp;
                firstScreen.firstScreenLoadEnd = lastImageLoadedStamp;
                firstScreen.duaring = lastImageLoadedStamp - performance.timing.navigationStart;
                
                reportData(firstScreen);
                return;
            }
        }
        return;
    }
    
    var imgEls = getImage();

    imgEls.forEach(function(el) {
        if(!imgLoadedHash.get(el)){
            var img = new Image();
            imgLoadedHash.put(el,{
                loaded: true,
            });
            img.onload = OnLoad;
            img.onerror = OnError;
            img.src = el.__src;
        }
    });
    pools[totalCounter+""] = {
        imgLen: imgEls.length,
        stamp: Date.now(),
        imgsLoadedCount: imgsLoadedCount
    };
    totalCounter += timeout;
}
watch dog采集

利用Mutation Observer API進(jìn)行偵聽(tīng) 內(nèi)容框的DOM事件,判斷首屏DOM結(jié)構(gòu)是否完備;如果構(gòu)建完畢則偵聽(tīng)首屏范圍內(nèi)的圖片加載事件,計(jì)算首屏?xí)r間。

watch dog需要知曉合適首屏DOM構(gòu)建完畢。這需要首屏計(jì)算模塊主動(dòng)插入一個(gè)打點(diǎn)標(biāo)簽

,將業(yè)務(wù)代碼放置在標(biāo)簽內(nèi)部(這個(gè)步驟最好放在發(fā)布階段,由腳手架操作)。通過(guò)mutation 偵聽(tīng) .j_collector_container 容器的DOM子孫節(jié)點(diǎn)變化。如在observe事件處理函數(shù)中,計(jì)算 .j_collector_container 高度,如果大于屏幕高度則意味著首屏的DOM結(jié)構(gòu)已渲染完畢,開(kāi)始計(jì)算首屏?xí)r間。

在計(jì)算 .j_collector_container 高度時(shí),最好采用限流策略,防止短時(shí)間內(nèi)計(jì)算多次容器的布局信息,這也是無(wú)可奈何之舉。

此處的偽代碼如下:

// 記錄首屏DOM元素的位置信息
var firstScreenDomReady = false;
var callback = function(records){
    if(firstScreenDomReady)
        return;

    // 此處需做throttle 處理
    for(var i=0,len=records.length;i= screenHeight){
            firstScreenDomReady = true;
            recordFirstScreenLoad();
            return;
        }
    }
};
    
var mo = new MutationObserver(callback);

var option = {
    "childList": true,
    "subtree": true
};

var collectWrapper = document.querySelector(".j_collector_wrapper");
if(collectWrapper.getBoundingClientRect().height < win.innerHeight){
    mo.observe(collectWrapper, option);
}else{
    setTimeout(function(){
        recordFirstScreenLoad();
    });
}
總結(jié)

不管采用哪種方式,計(jì)算出來(lái)的首屏?xí)r間都不是準(zhǔn)確的。而且在每種實(shí)現(xiàn)中都需要通過(guò)JS引擎與渲染引擎的bridge進(jìn)行通信執(zhí)行耗時(shí)的操作,如getBoundingClientRect和訪(fǎng)問(wèn)offsetTop屬性導(dǎo)致relayout。不過(guò)這也是沒(méi)有辦法的辦法,在瀏覽器不提供相關(guān)首屏API的前提下我們只有這么做。

另外,對(duì)比這三種實(shí)現(xiàn)(開(kāi)發(fā)者手動(dòng)打點(diǎn)、輪訓(xùn)、watch dog采集),針對(duì)一個(gè)復(fù)雜的電商首屏做了性能測(cè)試,該頁(yè)面首屏部分有7個(gè)非常復(fù)雜的子組件,得到如下結(jié)果:

結(jié)果也符合我們的預(yù)期。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/51755.html

相關(guān)文章

  • 關(guān)于首屏時(shí)間采集動(dòng)化解決方案

    摘要:關(guān)于首屏首屏?xí)r間是指從轉(zhuǎn)向該頁(yè)面到屏幕中該頁(yè)面所有內(nèi)容都可見(jiàn)時(shí)的時(shí)間。如在事件處理函數(shù)中,計(jì)算高度,如果大于屏幕高度則意味著首屏的結(jié)構(gòu)已渲染完畢,開(kāi)始計(jì)算首屏?xí)r間。 關(guān)于首屏 首屏?xí)r間是指從轉(zhuǎn)向該頁(yè)面到屏幕中該頁(yè)面所有內(nèi)容都可見(jiàn)時(shí)的時(shí)間。已經(jīng)有太多的關(guān)于首屏?xí)r間的計(jì)算,在本文中并不重復(fù)闡述這些已經(jīng)被提出或者實(shí)現(xiàn)的方案,而旨在探索與討論更多的首屏自動(dòng)化采集方案,擴(kuò)大思考范圍,你我思想之間...

    1treeS 評(píng)論0 收藏0
  • [聊一聊系列]聊一聊前端速度統(tǒng)計(jì)(性能統(tǒng)計(jì))那些事兒

    摘要:性能統(tǒng)計(jì)有助于幫我們檢測(cè)網(wǎng)站的用戶(hù)體驗(yàn)。這樣,我們就輕輕松松的統(tǒng)計(jì)到了首屏?xí)r間。下一章,我們將繼續(xù)聊聊百度移動(dòng)版首頁(yè)那些事。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼): https://segmentfault.com/blog/frontenddriver 上一篇文章我們討論了,如何進(jìn)行前端日志打點(diǎn)統(tǒng)計(jì): https://segm...

    gclove 評(píng)論0 收藏0
  • [聊一聊系列]聊一聊前端速度統(tǒng)計(jì)(性能統(tǒng)計(jì))那些事兒

    摘要:性能統(tǒng)計(jì)有助于幫我們檢測(cè)網(wǎng)站的用戶(hù)體驗(yàn)。這樣,我們就輕輕松松的統(tǒng)計(jì)到了首屏?xí)r間。下一章,我們將繼續(xù)聊聊百度移動(dòng)版首頁(yè)那些事。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼): https://segmentfault.com/blog/frontenddriver 上一篇文章我們討論了,如何進(jìn)行前端日志打點(diǎn)統(tǒng)計(jì): https://segm...

    Karuru 評(píng)論0 收藏0
  • 讓前端監(jiān)控?cái)?shù)據(jù)采集更高效

    摘要:如何在新的技術(shù)背景下讓前端數(shù)據(jù)采集工作更加完善高效,是本文討論的重點(diǎn)。具體來(lái)說(shuō),我們對(duì)前端的數(shù)據(jù)采集具體主要分為路由切換性能資源錯(cuò)誤日志上報(bào)路由切換等前端技術(shù)的快速發(fā)展使單頁(yè)面應(yīng)用盛行。 隨著業(yè)務(wù)的快速發(fā)展,我們對(duì)生產(chǎn)環(huán)境下的問(wèn)題感知能力越來(lái)越關(guān)注。作為距離用戶(hù)最近的一層,前端的表現(xiàn)是否可靠、穩(wěn)定、好用,很大程度上決定著用戶(hù)對(duì)整個(gè)產(chǎn)品的體驗(yàn)和感受。因此,對(duì)于前端的監(jiān)控不容忽視。 搭建一...

    Half 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<