大背景
操控性强化是大部份后端人的崇尚,在那条马路上,方式各种各样。这首诗,说呵呵能什么样表述测试方式及呈报。
分项
FP
涵义FP,全名 First Paint,译者为首度绘出,是天数圣戈当斯区的第三个天数点,它代表者网页的第三个画素图形到萤幕上所制天数,也是页面在萤幕上首度出现听觉变动的天数。
统计数据方式论透过performance.getEntriesByType(paint’),取第三个pain的天数。如:
function getFPTime(){
const timings = performance.getEntriesByType(paint)[0];
return timings ? Math.round(timings.startTime) :null}
FCP
涵义FCP,全名 First Contentful Paint,译者为首度文档绘出,简而言之,它代表者应用程序第二次向萤幕绘文档。
特别注意:多于首度绘出文档、图片(包涵左上方)、非紫色的canvas或SVG时才被算是FCP。
统计数据方式论透过performance.getEntriesByType(paint’),取第三个pain的天数,或是透过Mutation Observer观察到首度节点变动的天数。如:
constdomEntries = []
const observer = new MutationObserver((mutationsList)=>{
for(var mutation ofmutationsList) {
if (mutation.type == childList) {
console.log(A child node has been added or removed.);
}
if (mutation.type == addedNodes) {
//TODO新增了节点,做处理,计算此时的可见性/位置/出现天数等信息,然后 push 进数组…
domEntries.push(mutation)
}
}
});
function getFPTime(){
const timings = performance.getEntriesByType(paint);
if(timings.length >1)return timings[1]
return timings ? Math.round(timings.startTime) : null //伪代码,算 DOM 变动时的最小那个天数,即节点首度变动的天数 return Math.round(domEntries.length ? Math.min(…domEntries.map(entry =>entry.time)) :0);
}
MutationObserver 理解及使用补充:
https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserverhttps://javascript.ruanyifeng.com/dom/mutationobserver.html特别注意FP与FCP这两个分项之间的主要区别是:FP是当应用程序开始绘出文档到萤幕上的时候,只要在听觉上开始出现变动,无论是什么文档触发的听觉变动,在这一刻,这个天数点,叫做FP。
相比之下,FCP指的是应用程序首度绘出来自DOM的文档。例如:文档,相片,SVG,canvas元素等,这个天数点叫FCP。
FP和FCP可能是相同的天数,也可能是先FP后FCP。
FMP
涵义FMP,全名 First Meaningful Paint,译者为首度有意义的绘出,是页面主要文档出现在萤幕上的天数, 这是用户感知加载体验的主要分项。目前尚无标准化的表述, 因为很难以通用的方式去确定各种类型页面的关键文档。
统计数据方式论目前没有统一方式论,阿里有个标准为最高可见增量元素,采用深度优先遍历方式,详细可见:https://zhuanlan.zhihu.com/p/44933789
其次,能自表述,比如通 Mutation Observer 观察页面加载的一段天数(如前20s)内页面节点的变动, 即元素新增/移除/隐藏等变化记录下来,这样能得到页面元素的可见天数点及元素与可视区域的交叉信息等。
然后,自表述一个计算公式,比如根据元素的类型进行权重取值(div 权重1,img 权重2等), 然后取元素与可视区域的交叉区域面积、可见度、 权重值之间的乘积为元素评分。
根据上面得到的信息, 以天数点为X轴, 该天数点可见元素的评分总和为Y轴, 取最高点对应的最小天数为页面主要文档出现在萤幕上的天数。
FID
涵义FID,全名 First Input Delay,译者为首度输入延迟,是测量用户首度与您的站点交互时的天数(即当他们单击链接/点击按钮/使用自表述的JavaScript驱动控件时)到应用程序实际能够回应这种互动的天数。
统计数据方式论方式一,透过performanceObserver(目前支持性为88.78%)观察类型为first-input的entry,获得其startTime/duration等数即可
方式二,初始化时为特定事件类型(click/touch/keydown)绑定通用统计数据方式论事件,开始调用时从event.timeStamp取开始处理的天数(这个天数是首度输入延迟天数),在事件处理中注册requestIdleCallback事件回调onIdleCallback,当onIdleCallback被执行时,当前天数减开始的event.timeStamp即为duration天数
参考代码:
// 方式一function getFIDTime(){
const timings = performance.getEntriesByType(first-input)[0];
returntimings ? timings :null}
// 方式二,以下代码仅代表者思路[click,touch,keydown].forEach(eventType =>{
window.addEventListener(eventType, eventHandle);
});
function eventHandle(e){
consteventTime = e.timeStamp;
window.requestIdleCallback(onIdleCallback.bind(this, eventTime, e));
}
function onIdleCallback(eventTime, e){
const now = window.performance.now();
constduration = now – eventTime;
return{
duration: Math.round(duration),
timestamp: Math.round(eventTime)
}
[click,touch,keydown].forEach(eventType =>{
window.removeEventListener(eventType, eventHandle);
});
}
Event 对象的更多理解:https://developer.mozilla.org/zh-CN/docs/Web/API/Event
TTI
涵义TTI,全名 Time To Interactive,译者为可交互天数,指的是应用在听觉上都已图形出了,完全能响应用户的输入了。是衡量应用加载所需天数并能够快速响应用户交互的分项
统计数据方式论与 FMP 相同,很难规范化适用于大部份页面的 TTI 分项表述。
统计数据方式一:谷歌实验室写的npm包,tti-polyfill
import ttiPolyfill from tti-polyfill;
ttiPolyfill.getFirstConsistentlyInteractive().then((tti) =>{
ga(send, event, {
eventCategory:Performance Metrics,
eventAction:TTI,
eventValue: tti,
nonInteraction: true,
});
});
统计数据方式二:在页面加载的一定天数内(如前50s内),以(domContentLoadedEventStart-navigationStart)+5为起始点,循环寻找,找到一个5s的窗口,其中网络请求不超过2个且没有长任务(>50ms),再找到该5秒窗口之前的最后一个长任务,该长任务结束的天数点是可稳定交互天数。其中长任
// 以下代码仅代表者思路const basicTime = 5000;
function getTTITime(startTime,longTaskEntries, resourceEntries,domContentLoadedTime){
letbusyNetworkInWindow = [];
lettti = startTime;
while (startTime + basicTime <= 50000) { //从前50s 中去找tti = startTime;
longTasksInWindow = longTaskEntries.filter(task =>{
returntask.startTime < startTime + basicTime && task.startTime + task.duration > startTime;
});
if(longTasksInWindow.length) {
constlastLongTask = longTasksInWindow[longTasksInWindow.length –1];
startTime = lastLongTask.startTime + lastLongTask.duration;
continue;
}
busyNetworkInWindow = resourceEntries.filter(request =>{
return!(request.startTime >= startTime + basicTime || request.startTime + request.duration <= startTime);
});
if (busyNetworkInWindow.length > 2) {
constfirstRequest = busyNetworkInWindow[0];
startTime = firstRequest.startTime + firstRequest.duration;
continue;
}
return Math.max(tti, domContentLoadedTime);
}
return Math.max(tti, domContentLoadedTime);
}
FCI
涵义FCI,全名 First CPU Idle,译者为首度CPU空闲天数代表者着一个页面已经满足了最小程度的与用户出现交互行为的时刻。当我们打开一个页面,我们并不需要等到一个页面完全加载好了,每一个元素都已经完成了图形,然后再去与页面进行交互行为。页面满足了我们基本的交互的天数点是衡量页面操控性的一个重要分项。
统计数据方式论FCI为在FMP之后,首度在一定窗口天数内没有长任务出现的那一时刻,并且如果这个天数点早于DOMContentLoaded天数,那么FCI的天数为DOMContentLoaded天数,窗口天数的计算函数能根据Lighthouse提供的计算公式 N = f(t) = 4 * e^(-0.045 * t) + 1 进行自表述设计
FPS
涵义FPS,全名 Frames Per Second,译者为每秒帧率,表示的是每秒钟画面更新次数,当今大多数设备的萤幕刷新率都是60次/秒。
参考标准:
帧率能够达到 50 ~ 60 FPS 的动画将会相当流畅,让人倍感舒适;帧率在 30 ~ 50 FPS 之间的动画,因各人敏感程度不同,舒适度因人而异;帧率在 30 FPS 以下的动画,让人感觉到明显的卡顿和不适感;帧率波动很大的动画,亦会使人感觉到卡顿统计数据方式论利用requestAnimationFrame,循环调用,当now大于lastTime+1S时,计算FPS。若小于某个阀值则能认为当前帧率较差,若连续小于多个阀值,则停止统计数据,当前页面处于卡顿状态,进入卡顿处理方式论
更多具体参考:
https://www.cnblogs.com/coco1s/p/8029582.html设备信息
从window.navigator
从window.devicePixelRatio。
呈报思路
pv/uv监听各种页面切换的情况;SPA页面,能监听hashChange
操控性数据/设备信息/网络状况在页面离开前呈报,beforeUnload/visibilitychange/pagehide…+sendBeancon/Ajaximg 标签+切片+压缩总结
用图说话,本文文档,整理到了一张图上。
参考资料
https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics?hl=zh-cnhttps://www.w3.org/TR/DOM-Level-3-Events/#events-mutationeventshttps://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserverhttps://javascript.ruanyifeng.com/dom/mutationobserver.htmlhttps://developer.mozilla.org/zh-CN/docs/Web/API/Eventhttps://www.cnblogs.com/coco1s/p/8029582.html最后欢迎加我微信(winty230),拉你进技术群,长期交流学习…
…