浅谈前端监控(二)

页面加载时间

阶段计算表

字段描述计算方式意义
unload前一个页面卸载耗时unloadEventEnd – unloadEventStart
redirect重定向耗时redirectEnd – redirectStart重定向的时间
appCache缓存耗时domainLookupStart – fetchStart读取缓存的时间
dnsDNS解析耗时domainLookupEnd – domainLookupStart可观察域名解析服务是否正常
tcpTCP连接耗时connectEnd – connectStart建立连接的耗时
ssl安全连接耗时connectEnd – secureConnectiuonstart反映数据安全连接建立耗时
TTFB网络请求耗时responseStart – requestStartTTFB是发出页面请求到接收数据第一个字节的时间(ms)
response响应数据传输耗时`responseEnd – resoibseStart观察网络是否正常
domDOM解析耗时domInteractive – responseEnd观察DOM结构是否合理,是否有JS阻塞页面解析
dclDOMDOntentLoaded事件耗时domContentLoadedEventEnd – domContentLoadedEventStart当HTML文档完成加载和解析之后,DOMDOntentLoaded事件等待样式表\图像完成加载的时长
resources资源加载耗时domComplete – domContentLoadedEventEnd可观察文档流是否过大
domReadyDOM阶段渲染耗时rdomContentLoadedEventEnd – fetchStartDOM和页面资源加载完成时间,会触发 domDContentLoaded 事件
首次渲染耗时responseEnd – fetchStart加载文档到看到第一针非空图像的时间,(白屏时间)
首次可交互时间domInteractive – fetchStartDOM树解析完成时间,此时 document.readyState 为 interactive
首包时间耗时responseSyary – domainLookupStartDNS解析到响应返回给浏览器的第一个字节
页面完全加载时间loadEventStart – fetchStart
onLoadonLoad事件耗时loadEventEnd – loadEventSatrt

实现

值得注意的是 performance.timing 这个属性在MDN上标识为废弃属性, 推荐替换属性PerformanceTiming

onload(function(){
   var perfEntries = performance.getEntriesByType("navigation");
   setTimeout(()=>{
     const {
       fetchStart,
       connectStart,
       connectEnd,
       requestStart,
       responseStart,
       responseEnd,
       domInteractive,
       domContentLoadedEventStart,
       domContentLoadedEventEnd,
       loadEventStart
    } = perfEntries[0];
     
     let log = {
       kind:"experience",
       type:'timing',
       connectTime:connectStart -connectEnd , //连接时间
       ttfbTime:responseStart - requestStart, // 首字节到达时间
       responseTime:responseEnd - responseStart, // 响应的读取时间
       domContentLoadedTime:domContentLoadedEventEnd - domContentLoadedEventStart,// 资源全部加载完成时间
       timeToInteractive:domInteractive - fetchStart, // 首次可交互时间
       loadTime:loadEventStart - fetchStart, // 完整的加载时间
    }
     console.log("用户体验监控",log)
  },3000)

性能指标

字段描述备注
FP首次绘制包括自定义背景,表示的首次将像素绘制到屏幕的时间
FCP首次内容绘制第一个DOM渲染到屏幕的时间(也可以作为白屏时间)
FMP首次有意义绘制页面有意义的内容绘制时间(浏览器不知道那个元素是有意义的,需要在指定的html中加入 elementtiming属性,值可以随意填写)
LCP最大内容渲染代表在试图中最大的元素的加载时间
DCLDOM加载完成HTML加载解析之后,DOMCIntentLoaded时间被触发的时间,无需等待样式表、图像等加载
LonLoad当依赖的资源全部被加载完毕之后触发的时间
TTI可交互时间标记应用及进行渲染并可以相应用户输入的时间
FID首次输入延迟用户首次和页面交互时页面的响应时间(反射弧时间)

实现

function timing(){
  let FMP,LCP;
 // 添加性能条目的观察者
 new PerformanceObserver((entryList,observer)=>{
   let perfEntries = entryList.getEntries();
   FMP = perfEntries[0];
   observer.disconnect(); //取消观察
}).observe({entryTypes:['element']}); //观察页面中有意义的元素

 new PerformanceObserver((entryList,observer)=>{
   let perfEntries = entryList.getEntries();
   LCP = perfEntries[0];
   observer.disconnect(); //取消观察
}).observe({entryTypes:['largest-contentful-paint']}); // 观察页面最大渲染元素

 /**TTI首次延迟 OR FIO处理延迟时间 */
 new PerformanceObserver((entryList,observer)=>{
   let lastEvent = getLastEvent()
   let firstInput = entryList.getEntries()[0];
   if(firstInput){
     //inputDelay(反射弧时间) = processingStart(开始处理的时间) - startTime(开点击的时间)
     let inputDelay = firstInput.processingStart - firstInput.startTime;
     let duration = firstInput.duration; // 处理的耗时
     if(inputDelay>0 || duration>0){
       let log = {
         kind:"experience", // 用户体验指标
         type:"firstInputDelay", // 首次输入延迟
         inputDelay:inputDelay, // 延迟的时间
         duration:duration, // 处理的时间
         startTime:firstInput.startTime, // 反射弧时间
         selector:lastEvent?getSelector(lastEvent.path || lastEvent.target) : "", // 点击的元素
      }
       console.log("首次交互时长",log)
    }
  }
   observer.disconnect(); //取消观察
}).observe({type:"first-input",buffered:true}); // 观察第一次交互
 
 onload(()=>{
     setTimeout(()=>{
         let FP = performance.getEntriesByName("first-paint")[0]
         let FCP = performance.getEntriesByName("first-contentful-paint")[0];
         let paint_log = {
           kind:"experience", //用户体验指标,
           type:'paint', // 统计每个阶段的时间
           firstPaint:FP.startTime, // 首次绘制时间
           firstContentPaint:FCP.startTime, // 首次内容绘制时间
           firstMeaningfulPaint:FMP.startTime, // 首次意义绘制时间
           largestContentfulPaint:LCP.startTime, //最大内容渲染时间
        }
         console.log("-----性能监控---",paint_log)
    },2000)
})
}

上面表格中提到,在获取首次有意义绘制的耗时的时候,需要在HTML中添加一个 elementtiming 属性,属性值可以随意。 示例如下

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>前端监控SDK</title>
 <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.js"></script>
</head>

<body>
 <div class="container">
   <p>测试一下渲染速度</p>
 </div>

 <script>
   setTimeout(()=>{
     let content = document.getElementsByClassName("container")[0];
     let h1 = document.createElement("h1");
     h1.innerHTML = "我为啥是有意义的内容呀,因为我有elementtiming";
     h1.setAttribute("elementtiming","xxx")
     content.appendChild(h1)
  },2000)
 </script>
</body>
</html>

DEMO地址,每一个功能都在一个单独的commit中

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇