监控平台实现方案
监测网页加载时长是关注的是以下5个过程:
1.重定向时间:获取此网页前重定向所花费的时间
2.DNS域名查找时间:查找此网页的DNS所花费的时间
3.TCP服务器连接时间:用户连接到您的服务器所需的时间
4.服务器响应时间:您的服务器响应用户请求所需的时间,其中爆哭哟从用户所在位置连接到您的服务器所需的网络时间
5.网页下载时间:下载网页所需的时间
访问单页面经历的阶段
1.页面准备阶段 cache dns解析 tcp连接 ssl证书
2.页面加载阶段 html解析 css解析 js解析
3.页面渲染阶段 dom渲染 css渲染
4.页面交互阶段 js执行
性能指标
FP(First Paint)首次绘制:页面开始绘制的时间,包括任何文本、图像(包括背景图片)、非白色的canvas和svg元素
FCP(First Contentful Paint)首次内容绘制:浏览器将第一个DOM元素绘制到屏幕上的时间
LCP(Largest Contentful Paint)最大内容绘制:最大内容元素(文本、图片、视频等)加载并渲染到屏幕上的时间
FID(First Input Delay)首次输入延迟:用户首次与页面交互(例如点击链接、按钮等)到浏览器实际能够响应该交互的时间
CLS(Cumulative Layout Shift)累计布局偏移:测量整个页面生命周期内发生的所有意外布局偏移的度量值
TTI(Time to Interactive)可交互时间:页面完全加载并可以开始响应用户交互的时间
LCP(Largest Contentful Paint)最大内容绘制:最大内容元素(文本、图片、视频等)加载并渲染到屏幕上的时间
TBT(Total Blocking Time)总阻塞时间:测量主线程在首次内容绘制之前被阻塞的总时间
FMP(First Meaningful Paint)首次有意义绘制:页面主要内容加载并渲染到屏幕上的时间
TTFB(Time To First Byte)首字节时间:浏览器从服务器接收到第一个字节的时间
web-vitals 第三方库
能够自动统计页面各阶段加载时间 FP FCP CLS LP等等
PerformanceObserver性能监测对象
PerformanceObserver 用于监测性能度量事件,在浏览器的性能时间轴记录新的 performance entry 的时候将会被通知。
开发之前,要理解很多概念:
1.了解PerformanceObserver是什么?
概念:PerformanceObserver 用于监测性能度量事件,在浏览器的性能时间轴记录新的 performance entry 的时候将会被通知。
应用:
// 可以尝试输出performance.getEntries()
// 会得到页面上的静态资源加载耗时与资源大小
上面这一坨是什么???
这个就是每个静态资源在渲染,加载中的“痕迹”,开始渲染时间,结束时间,DNS解析时间,TCP链接时间,请求时间,响应时间,首字节加载时间,协议,各种资源大小等等等等,只要涉及到的数据,都会被记录在相应对象里。
2.大致了解了以后,说一下具体的使用方法
// 同performance.getEntries()输出一样,统计静态资源
function entryHandle(list) {
const entries = list.geteEntries();
for (const entry of entries) {
console.log(entry);
// 打印结果
// 可以根据对象的属性,得到想要统计的数值
// 发送数据进行上报
}
}
let observer = new PerformanceObserver(entryHandle)
observer.observe({type: ['resource'], buffered: true})// 统计静态资源
// observer.observe({type: 'paint', buffered: true}); // 统计fp/fcp
// observer.observe({type: 'largest-contentful-paint', buffered: true}); // 统计lcp
知道了这些所有的数据了,下面要做的,就是先统计需要的指标
1.静态资源
2.fp/fcp
3.统计lcp
4.页面加载时间
5.埋点
6.pv/uv
7.等等,待补充
截止2024.08.28,已经写好了前4个统计方法,后续全部写完,打包后供开发者使用
结合上一篇文章关于各个时间的统计,下面是其中observerEntries.js的代码,完整代码请见(目前正在开发中):
https://github.com/Mr-Shi-root/sdk-platform
// 静态资源需要在页面加载完成后调用
// 所以在页面加载完调用或者增加监听事件,在load时调用
export default function observerEntries(){
if (document.readyState == 'complete') {
observerEvent()
} else {
const onLoad = () => {
observerEvent()
window.removeEventListener('load', onLoad)
}
window.addEventListener('load', onLoad, true)
}
}
// 统计所有静态资源的方法
export function observerEvent() {
const entryHandle = (list) => {
const entries = list.geteEntries();
for (const entry of entries) {
if(observer) {
observer.disconnect();
}
// 需要上报的参数
const reporData = {
name: entry.name,
type: 'performance', //类型
subType: entry.entryType, // 类型
pageUrl: entry.initiatorType, // 资源管理
duration: entry.duration, // 耗时
dns: entry.domainLookupEnd - entry.domainLookupStart, // dns解析时间
tcp: entry.connectEnd - entry.connectStart, // tcp连接时间
redirect: entry.redirectEnd - entry.redirectStart, // 重定向时间
// TODO: 看下要不要减后面的requestStart
ttfb: entry.responseStart - entry.requestStart, // 首字节时间
protocol: entry.nextHopProtocol, // 协议
responseBodySize: entry.transferSize, // 响应大小
responseHeaderSize: entry.transferSize - entry.encodedBodySize, // 响应头大小
transferSize: entry.transferSize, // 请求内容大小
resourceSize: entry.decodedBodySize, // 响应内容大小(资源解压后的大小)
startTime: performance.now(),
}
console.log(entry);
// 发送数据进行上报
}
}
let observer = new PerformanceObserver(entryHandle)
observer.observe({type: ['resource'], buffered: true})
}