speed.js 4.21 KB
var reporter = require('./reporter');

// 首屏时间获取:
// 1,获取首屏基线高度
// 2,计算出基线dom元素之上的所有图片元素
// 3,所有图片onload之后为首屏显示时间
// 参考 https://www.zhihu.com/question/23212408/answer/56647975
function getOffsetTop(ele) {
    var offsetTop = ele.offsetTop;
    if (ele.offsetParent !== null) {
        offsetTop += getOffsetTop(ele.offsetParent);
    }
    return offsetTop;
}

var firstScreenHeight = window.screen.height;
var firstScreenImgs = [];
var isFindLastImg = false;
var allImgLoaded = false;
var firstScreenLoadTime = 0;
var t = setInterval(function() {
    var i, img;
    if (isFindLastImg) {
        if (firstScreenImgs.length) {
            for (i = 0; i < firstScreenImgs.length; i++) {
                img = firstScreenImgs[i];
                if (!img.complete) {
                    allImgLoaded = false;
                    break;
                } else {
                    allImgLoaded = true;
                }
            }
        } else {
            allImgLoaded = true;
        }
        if (allImgLoaded) {
            firstScreenLoadTime = (new Date()).getTime() - _timeStart
            clearInterval(t);
        }
    } else {
        var imgs = document.body && document.body.querySelectorAll('img') || [];
        for (i = 0; i < imgs.length; i++) {
            img = imgs[i];
            var imgOffsetTop = getOffsetTop(img);
            if (imgOffsetTop > firstScreenHeight) {
                isFindLastImg = true;
                break;
            } else if (imgOffsetTop <= firstScreenHeight && !img.hasPushed) {
                img.hasPushed = 1;
                firstScreenImgs.push(img);
            }
        }
    }
}, 0);

var speedReporter = {
    reportTime: function(speedList) {
        var speedStr = reporter.stringify(speedList);
        reporter.report(speedStr);
    },
    addEvent: function() {
        var self = this;
        var timeList = [];
        var pt = encodeURIComponent(location.href);
        var u = reporter.getUid();
        var ud = reporter.getUdid();
        var rid = reporter.getReqId();
        var pStart = window.performance && window.performance.timing.navigationStart || 0;
        var r = reporter.getRoute();

        _timeStart = window._timeStart || 0;

        document.addEventListener && document.addEventListener('DOMContentLoaded', function(event) {
            timeList.push({
                tp: 'dcl', // DOMContentLoaded
                t: (new Date()).getTime() - _timeStart,
                pt: pt,
                u: u,
                ud: ud,
                rid: rid,
                r: r
            });

            // 首屏加载速度
            var imgs = document.body && document.body.querySelectorAll('img') || [];
            if (!imgs.length) {
                isFindLastImg = true;
            }
        }, false);

        window.addEventListener && window.addEventListener('load', function(event) {
            timeList.push({
                tp: 'ld', // load
                t: (new Date()).getTime() - _timeStart,
                pt: pt,
                u: u,
                ud: ud,
                rid: rid,
                r: r
            });

            // 首屏加载速度
            allImgLoaded = true;
            isFindLastImg = true;
            if (t) {
                clearInterval(t);
            }
            if (firstScreenLoadTime) {
                timeList.push({
                    tp: 'fs', // firstScreenLoadTime
                    t: firstScreenLoadTime,
                    pt: pt,
                    u: u,
                    ud: ud,
                    rid: rid,
                    r: r
                });
            }

            timeList.push({
                tp: 'pf', // performance
                dcl: (window.performance && window.performance.timing.domComplete || 0) - pStart,
                ld: (window.performance && window.performance.timing.loadEventStart || 0) - pStart,
                pt: pt,
                u: u,
                ud: ud,
                rid: rid,
                r: r
            });

            self.reportTime(timeList);
        }, false);
    },
    init: function() {
        this.addEvent();
    }
};

module.exports = speedReporter;