1、chrome开发者工具-Performance面板
chrome浏览器右键检查元素即可打开谷歌开发者工具面板,但是常用的可能是Element、Console、Source三个面板的功能,其余面板还有:Network、Performance、Memory、Application、Security、Audits等。
这些按钮的功能如下:
* Elements: 查找网页源代码HTML中的任一元素,手动修改任一元素的属性和样式且能实时在浏览器里面得到反馈。
* Console: 记录开发者开发过程中的日志信息,且可以作为与JS进行交互的命令行shell。
* Sources: 断点调试JS。
* Network: 从发起网页页面请求Request后,分析HTTP请求后得到的各个请求资源信息(包括状态、资源类型、大小、所用时间等),可以根据这个进行网络性能优化。
* Performance: 记录并分析网站的生命周期内所发生的各类事件,以此可以提高网页的运行时间的性能。
* Memory: 可以查看Performance所能提供的更多信息。
* Application: 记录网站加载的所有资源信息,包括存储数据(LocalStorage、SessionStorage、InedxedDB、WebSQL、Cookie),缓存数据,字体,图片,脚本,样式等。
* Security: 判断当前网页是否安全。
* Audits: 对当前网页进行网络利用、网页性能方面的诊断,并给出一些优化建议。比如列出所有没有用到的css文件等。
关于各面板的详细使用情况,可以参考博客:
2、如何监控网页卡顿
要监控网页卡顿,必须从FPS说起。
FPS是来自视频或者游戏里的概念,即每秒的帧数,代表视频或游戏的流畅度,俗话说,就是‘不卡’。
那么在前端开发领域,什么是网页的FPS呢?
网页内容在不断变化之中,网页的FPS是浏览器在渲染这些变化时的帧率,帧率越高,用户感觉网页越流畅,反之则会感觉卡顿。
* 1、在chrome中可以通过开发者工具的performance面板查看网页的FPS(具体操作情况可点击1中的链接):
绿色的直方图即代表在页面重新绘制时的帧率,Frames为每一帧渲染所花的时间。
通过render里的FPS paint,可以查看当前网页更新时的FPS具体数值:
最优的帧率是60,即16.5ms左右渲染一次。
*2、FPS extension是Chrome的一个扩展,可以显示当前网页的FPS值,即页面是否卡顿。
这种工具获取页面FPS的方式与浏览器自身给出的方式不同,没有采用浏览器原生的API(正在制定),这类工具独辟蹊径,通过浏览器的requestAnimationFrame API(可以使用setInterval polyfill)来实现。
代码类似:
var lastTime = performance.now();
var frame = 0;
var lastFrameTime = performance.now();
var loop = function(time) {
var now = performance.now();
var fs = (now - lastFrameTime);
lastFrameTime = now;
var fps = Math.round( 1000/fs );
frame++;
if(now > 1000 + lastTime){
var fps = Math.round((frame*1000) / (now-lastTime)); //计算时间达到一秒后的帧数
frame = 0; //清零
lastTime = now; //重新计算下一秒的帧数
};
window.requestAnimationFrame(loop);
}
(代码摘自淘宝前端团队的《无线性能优化:FPS测试》)
通俗的解释就是,通过requestAnimationFrame API 来定时执行一些JS代码,1s中frame无法达到60帧,即可间接地反映浏览器的渲染帧率。关于requestAnimationFrame API的细节,可以参看文档MDN文档。
如何监控网页卡顿
监控目的: 比如在全民直播时,我们必须重视用户的观看体验。所以任何网页或者播放器必须监控起来,以此指导优化,避免卡顿的出现。
方式: 以全民直播为例,使用FPS extension类似的方式(写一段JS循环运行达到监控目的),每秒中计算一次网页的FPS值,获得一列数据:
…6,8,11,23,25,35,44,50,39,34,…
然后通过通用的日志通道,上报到大数据平台进行分析即可。
那如何通过FPS确定网页存在卡顿呢?
观察结论:连续出现3个低于20的FPS 即可认为网页存在卡顿。
通过这种方式,得到了网页卡顿的统计数据,接下来,针对卡顿的问题,在有数据支持的情况下进行网页优化。
内容来源:知乎寸志,感谢作者分享!
3、如何监控网页崩溃
1、崩溃和卡顿的区别
卡顿也就是网页暂时响应比较慢,JS可能无法及时执行,这也是检测网页卡顿所依赖的技术点。
但崩溃就不一样了,网页都崩溃了,页面看不见了,JS无法运行,还有什么办法可以监控网页的崩溃?并将网页的崩溃上报呢?
2、基于Service Worker的崩溃方案统计
随着PWA概念的流行,大家对Service Worker也逐渐熟悉起来。基于以下原因,我们可以使用Service Worker来实现网页崩溃的监控:
*1、Service Worker有自己独立的工作线程,与网页区分开,网页崩溃了,Service Worker一般情况下不会崩溃;
*2、Service Worker生命周期一般比网页还要长,可以用来监控网页的状态;
*3、网页可以通过**navigator.serviceWorker.controller.postMessage**API向掌管自己的SW发送消息。
基于以上几点,我们可以实现一种基于心跳检测 的监控方案:
*P1:网页加载后,通过**postMessage**API每5s给sw发送一个心跳,表示自己在线,sw将在线的网页登记下来,更新登记时间;
*P2:网页在beforeunload时,通过**postMessage**API告知sw自己已经正常关闭,sw将登记的网页清除;
*P3:如果网页在运行的过程中crash了,sw中的running状态将不会被清除,更新时间停留在崩溃前的最后一次心跳;
*P4:Service Worker每10s查看一遍登记中的网页,发现登记时间已经超出了一定时间(比如15s),即可判定该网页crash了。
一些简化后的测试代码,供参考:
if(navigator.serviceWorker.controller !== null){
let HEARTBEAT_INTERVAL = 5 * 1000;//每5s发一次心跳
let sessionId = uuid();
let heartbeat = function () {
navigator.serviceWorker.controller.postMessage({
type: 'heartbeat',
id: sessionId,
data: {} //附加信息,如果页面crash,上报的附加数据
});
}
window.addEventListener('beforeunload',function() {
navigator.serviceWorker.controller.postMessage({
type: 'unload',
id: sessionId
});
});
setInterval(heartbeat,HEARTBEAT_INTERVAL);
heartbeat();
}
- sessionId: 本次页面会话唯一的id;
- postMessage: 附带一些信息,用于上报crash需要的数据,比如当前页面的地址等。
const CHECK_CRASH_INTERVAL = 10*1000; //每10s检查一次
const CRASH_THRESHOLD = 15 * 1000; //超过15s没有心跳则认为已经crash
const pages = {}
let timer
function checkCrash() {
const now = Date.now()
for ( var id in pages){
let page = pages[id]
if((now-page.t)>CRASH_THRESHOLD) {
//上报 crash
delete pages[id]
}
}
if(Object.keys(pages).length == 0) {
clearInterval(timer)
timer = null
}
}
worker.addEventListener('message', (e)=>{
const data = e.data;
if(data.type === 'heartbeat'){
pages[data.id] = {
t: Data.now()
}
if(!timer){
timer = setInterval(function(){
checkCrash()
},CHECK_CRASH_INTERVAL)
}
}else if(data.type === 'unload'){
delete pages[data.id]
}
})
方案的可行性
* **1、兼容性**Service Worker的普及率已经相当高了,鉴于国内各种浏览器都是Chrome内核,而且版本已经在Chrome45以上,已经覆盖了相当一部分用户。作为监控,数据覆盖大部分就好。
* 2、可靠性
相比于利用window对象的load与beforeunload事件实现网页崩溃的监控,利用service Worker更加可靠。
在页面加载时(load事件)在sessionStorage记录good_exit状态为pending,如果用户正常退出(beforeunload事件),good_exit状态改为true,如果页面crash了,good_exit状态依然为pending,在用户第二次访问网页的时候(第2个load事件),查看good_exit的状态,如果仍然是pending,就可以断定上次访问网页崩溃了。
代码:
window.addEventListener('load', function() {
sessionStorage.setItem('good_exit', 'pending');
setInterval(function(){
sessionStorage.setItem('time_before_crash', new Date().toString());
},1000);
});
window.addEventListener('beforeunload',function() {
sessionStorage.setItem('good_exit','true');
});
if( sessionStorage.getItem('good_exit') && sessionStorage.getItem('good_exit')!== 'true'){
/*insert crash logging code here*/
alert('Hey,welcome back from your crash, looks like you crashed on: ' +sessionStorage.getItem('time_before_crash'));
}
这个方案的问题所在之处:
1、采用sessionStorage存储状态,但通常网页崩溃/卡死后,用户会强制关闭网页或者索性重新打开浏览器,sessionStorage存储的状态将不复存在。
2、如果将存储状态在localStorage甚至Cookie中,如果用户先后打开多个网页,但不关闭,good_exit存储的一直都是pending,那么,每有一次网页打开,就会有一个crash上报。