整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

前端如何计算首屏加载时间

前端如何计算首屏加载时间

屏加载

首先,咱得明白什么是“首屏加载”时间。

答:用户能够看到第一屏区域内所有元素加载完的时间就是“首屏加载”时间。一个页面的“总加载时间”(onload)一定大于等于“首屏加载”时长。

通常需要考虑首屏时间的页面,都是因为在首屏位置内放入了较多的图片资源。

而图片资源处理是异步的,会先将图片长宽应用于页面排版,然后随着收到图片数据由上至下绘制显示的。并且浏览器对每个页面的TCP连接数限制,使得并不是所有图片都能立刻开始下载和显示。

所以我们需要获取首屏内最后一张图片加载完的时间(绑定首屏内所有图片的 load 事件),然后减去 navigationStart 时间,则为“首屏加载”时间。

首屏位置调用 API 开始统计 -> 绑定首屏内所有图片的 load 事件 -> 页面加载完后判断图片是否在首屏内,找出加载最慢的一张 -> 首屏时间
复制代码

白屏时间计算?

白屏时间=开始渲染时间(首字节时间+HTML下载完成时间)+头部资源加载时间。

// PerformanceTiming
performance.timing.responseStart - performance.timing.navigationStart

// or 在 chrome 高版本下
(chrome.loadTimes().firstPaintTime - chrome.loadTimes().startLoadTime)*1000

用户可操作时间(即 document.ready)

performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart

onload 总下载时间?

performance.timing.loadEventEnd - performance.timing.navigationStart

然我在其它地方也写过这篇文章,这里也写一下吧。

在前端或小程序开发中,有时候有一个需求,就是获得选择照片的拍摄时间。不过,选择照片之后能够获得的时间是最新的修改时间,有时候还不太正确。但是,我们还是有办法去解析照片的拍摄时间的,这就要说到EXIF了。

一般而言,使用移动设备的相机应用所拍摄的照片都是带EXIF信息的JPG格式。EXIF信息就会记录拍照片的设备型号、时间等信息,不过JPG格式并没有要求必须携带EXIF信息,所以有些照片是没有EXIF信息的。EXIF信息也是可以被修改和删除的。虽然有解析库可以使用,但我们就直接写一个代码,不用库,代码如下:

parseImage(data){
        // data为ArrayBuffer类型的JPG文件的二进制数据
        let arr=new Uint8Array(data);
        let base=0; // TIFF数据头开始地址
        let timeTagIndex=0; // EXIF时间信息标记开始地址
        for(let i=0;i<arr.length;i++){
            // 获取TIFF数据头地址
            if(arr[i]==69 && arr[i+1]==120 && arr[i+2]==105 && arr[i+3]==102 && arr[i+4]==0 && arr[i+5]==0){
                base=i+6;
            }
            // 获取时间标签地址
            if(arr[i]==0x90 && arr[i+1]==0x03){
                timeTagIndex=i;
                break; // 因为这个if的条件比较容易重复,但是我们要的是第一个,所以这里就可以直接退出了
            }
        }
       
        let bias=0; // 偏移地址
        for(let i=0;i<=3;i++){
             bias=bias<<8;
             bias+=arr[timeTagIndex+8+i];
        }        
        let datetime_addr_index=base+bias; // 实际地址

        let datetimestr=""; // 日期字符串
        for(let i=datetime_addr_index;i<=datetime_addr_index+19;i++){
            datetimestr+=String.fromCharCode(arr[i]);
        }
        
        return datetimestr; // 接着,我们可以将日期字符串进行一定的字符串和日期时间处理,以满足需要
    }

这个代码,在浏览器端和小程序中都是可以使用的。选择照片文件之后,一般可以读取到它的ArrayBuffer,这个ArrayBuffer包含了照片中的每一个字节。将ArrayBuffer传入这个函数,它会解析然后返回“年:月:日 时:分:秒”格式的、代表日期含义的字符串。

关于第3行代码,因为ArrayBuffer是不能直接操作的,因此要把它转换为TypedArray,TypedArray有很多种,那么选那种比较好呢?由于在格式解析中,我们喜欢用0x00~0xff中的一个值来表示一个字节,而Uint8Array中每个元素的取值正好是0x00~0xff(即0~255),因此选择Uint8Array这种TypedArray是比较合适的。

关于第7~10行代码,EXIF有很多种格式,最常用的是TIFF。EXIF数据的前6个字节称为EXIF数据头,之后则是TIFF数据头和TIFF数据。

在EXIF数据头中,前四个字节是Exif的ASCII码(注意大小写),后面是2个字节的0x00。

关于第11~15行代码,在这里,我们获取到了时间信息存储的位置。在TIFF中,存储的比如型号、时间等各种类型的信息,被称为一个标签。每一个标签占用12个字节:2个字节(表示这个标签代表什么含义,意思就是说后面的10个字节是什么型号还是时间还是什么,如果代表时间,则这两个字节一定是0x9003)+2个字节(代表用什么格式存储,时间标签的情况下这里的值一般是0x0002,代表值使用ASCII码的格式进行存储)+4个字节(代表值会占用多少个字节,时间标签规定值一定是20个字节)+4个字节(该标签的值或者值所在地址,因为这里只有4个字节,而时间的值一定有20个字节,因此在此时这里存储的是时间标签的值所在的地址,而不是具体的值,在TIFF中,所有地址都是从TIFF数据头的第一个字节所在地址开始计算的,因此我们需要知道TIFF数据头的地址,然后时间值的地址就是TIFF数据头的地址加上这个值)。

关于第25~28行代码,我们根据上面获取到的时间标签所在位置,读取20个字节,这20个字节就是EXIF中的时间信息了。

加载图片是提高用户体验的一个很好方法。图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度。

这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速、无缝地发布,也可帮助用户在浏览你网站内容时获得更好的用户体验。本文将分享三个不同的预加载技术,来增强网站的性能与可用性。

方法一:用css和JavaScript实现预加载

实现预加载图片有很多方法,包括使用css、JavaScript及两者的各种组合。这些技术可根据不同设计场景设计出相应的解决方案,十分高效。

单纯使用CSS,可容易、高效地预加载图片,代码如下:

#preload-01 { background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }  
#preload-02 { background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }  
#preload-03 { background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; }

将这三个ID选择器应用到(X)html元素中,我们便可通过CSS的background属性将图片预加载到屏幕外的背景上。

只要这些图片的路径保持不变,当它们在Web页面的其他地方被调用时,浏览器就会在渲染过程中使用预加载(缓存)的图片。简单、高效,不需要任何JavaScript。

该方法虽然高效,但仍有改进余地。使用该法加载的图片会同页面的其他内容一起加载,增加了页面的整体加载时间。

为了解决这个问题,我们增加了一些JavaScript代码,来推迟预加载的时间,直到页面加载完毕。代码如下:

function preloader() {  
    if (document.getElementById) {  
        document.getElementById("preload-01").style.background="url(http://domain.tld/image-01.png) no-repeat -9999px -9999px";  
        document.getElementById("preload-02").style.background="url(http://domain.tld/image-02.png) no-repeat -9999px -9999px";  
        document.getElementById("preload-03").style.background="url(http://domain.tld/image-03.png) no-repeat -9999px -9999px";  
    }  
}  
function addLoadEvent(func) {  
    var oldonload=window.onload;  
    if (typeof window.onload !='function') {  
        window.onload=func;  
    } else {  
        window.onload=function() {  
            if (oldonload) {  
                oldonload();  
            }  
            func();  
        }  
    }  
}  
addLoadEvent(preloader);

在该脚本的第一部分,我们获取使用类选择器的元素,并为其设置了background属性,以预加载不同的图片。

该脚本的第二部分,我们使用addLoadEvent()函数来延迟preloader()函数的加载时间,直到页面加载完毕。

如果JavaScript无法在用户的浏览器中正常运行,会发生什么?很简单,图片不会被预加载,当页面调用图片时,正常显示即可。

方法二:仅使用JavaScript实现预加载

上述方法有时确实很高效,但我们逐渐发现它在实际实现过程中会耗费太多时间。相反,我更喜欢使用纯JavaScript来实现图片的预加载。

下面将提供两种这样的预加载方法,它们可以很漂亮地工作于所有现代浏览器之上。

JavaScript代码段1

只需简单编辑、加载所需要图片的路径与名称即可,很容易实现:

<div class="hidden">  
    <script type="text/javascript">  
           var images=new Array()  
            function preload() {  
                for (i=0; i < preload.arguments.length; i++) {  
                    images[i]=new Image()  
                    images[i].src=preload.arguments[i]  
                }  
            }  
            preload(  
                "http://domain.tld/gallery/image-001.jpg",  
                "http://domain.tld/gallery/image-002.jpg",  
                "http://domain.tld/gallery/image-003.jpg"  
            )  
</script> 
</div>

该方法尤其适用预加载大量的图片。我的画廊网站使用该技术,预加载图片数量达50多张。将该脚本应用到登录页面,只要用户输入登录帐号,大部分画廊图片将被预加载。

JavaScript代码段2

该方法与上面的方法类似,也可以预加载任意数量的图片。将下面的脚本添加入任何Web页中,根据程序指令进行编辑即可。

<div class="hidden">  
    <script type="text/javascript">  
            if (document.images) {  
                img1=new Image();  
                img2=new Image();  
                img3=new Image();  
                img1.src="http://domain.tld/path/to/image-001.gif";  
                img2.src="http://domain.tld/path/to/image-002.gif";  
                img3.src="http://domain.tld/path/to/image-003.gif";  
            }    
</script>  
</div>

正如所看见,每加载一个图片都需要创建一个变量,如“img1=new Image();”,及图片源地址声明,如“img3.src=“../path/to/image-003.gif”;”。参考该模式,你可根据需要加载任意多的图片。

我们又对该方法进行了改进。将该脚本封装入一个函数中,并使用 addLoadEvent(),延迟预加载时间,直到页面加载完毕。

function preloader() {  
    if (document.images) {  
        var img1=new Image();  
        var img2=new Image();  
        var img3=new Image();  
        img1.src="http://domain.tld/path/to/image-001.gif";  
        img2.src="http://domain.tld/path/to/image-002.gif";  
        img3.src="http://domain.tld/path/to/image-003.gif";  
    }  
}  
function addLoadEvent(func) {  
    var oldonload=window.onload;  
    if (typeof window.onload !='function') {  
        window.onload=func;  
    } else {  
        window.onload=function() {  
            if (oldonload) {  
                oldonload();  
            }  
            func();  
        }  
    }  
}  
addLoadEvent(preloader);

方法三:使用Ajax实现预加载

上面所给出的方法似乎不够酷,那现在来看一个使用Ajax实现图片预加载的方法。该方法利用DOM,不仅仅预加载图片,还会预加载CSS、JavaScript等相关的东西。使用Ajax,比直接使用JavaScript,优越之处在于JavaScript和CSS的加载不会影响到当前页面。该方法简洁、高效。

window.onload=function() {  
    setTimeout(function() {  
        // XHR to request a js and a CSS  
        var xhr=new XMLHttpRequest();  
        xhr.open('GET', 'http://domain.tld/preload.js');  
        xhr.send('');  
        xhr=new XMLHttpRequest();  
        xhr.open('GET', 'http://domain.tld/preload.css');  
        xhr.send('');  
        // preload image  
        new Image().src="http://domain.tld/preload.png";  
    }, 1000);  
};

上面代码预加载了“preload.js”、“preload.css”和“preload.png”。1000毫秒的超时是为了防止脚本挂起,而导致正常页面出现功能问题。

下面,我们看看如何用JavaScript来实现该加载过程:

window.onload=function() {  
    setTimeout(function() {  
        // reference to <head>  
        var head=document.getElementsByTagName('head')[0];  
        // a new CSS  
        var css=document.createElement('link');  
        css.type="text/css";  
        css.rel="stylesheet";  
        css.href="http://domain.tld/preload.css";  
        // a new JS  
        var js=document.createElement("script");  
        js.type="text/javascript";  
        js.src="http://domain.tld/preload.js";  
        // preload JS and CSS  
        head.appendChild(css);  
        head.appendChild(js);  
        // preload image  
        new Image().src="http://domain.tld/preload.png";  
    }, 1000); 
};

这里,我们通过DOM创建三个元素来实现三个文件的预加载。正如上面提到的那样,使用Ajax,加载文件不会应用到加载页面上。从这点上看,Ajax方法优越于JavaScript。


- End -