performance-report頁面效能、資源、錯誤、ajax,fetch請求上報外掛 完善小巧

zane1發表於2019-03-04

performance-report只做頁面效能資料的採集和上報,是比較完整和健全的資料上報外掛,它可以幫你完成以下功能:

  • 當前頁面URL (data.page)

  • 上一頁面URL (data.preUrl)

  • 當前瀏覽器版本資訊 (data.appVersion)

  • 頁面效能資料資訊 (data.performance),例如:頁面載入時間,白屏時間,dns解析時間等

  • 當前頁面錯誤資訊 (data.errorList) 包含(js,css,img,ajax,fetch 等錯誤資訊)

  • 當前頁面所有資源效能資料 (data.resoruceList),例如ajax,css,img等資源載入效能資料

  • 不用擔心阻塞頁面,壓縮資源大小6kb,上報方式為非同步上報

github地址,如果你覺得對你有用的話歡迎給個star

github.com/wangweiange…

npm地址:

www.npmjs.com/package/per…

完整的前端效能監控系統

github.com/wangweiange…

html頁面直接引用:

  • 1、下載 dist/performance-report.min.js 到本地
  • 使用script標籤引入到html的頭部(備註:放到所有js資源之前)

  • 3、使用performance函式進行資料的監聽上報

<html>
<head>
	<meta charset="UTF-8">
	<title>performance test</title>
	<!-- 放到所有資源之前 防止獲取不到error資訊 -->
	<script src="../dist/performance-report.min.js"></script>
	<script>
		//開始上報資料
		Performance({
		    domain:`http://some.com/api`, //更改成你自己的上報地址域名
		})
	</script>
</head>複製程式碼

webpack使用

npm install performance-report --save-dev複製程式碼
//New performance.js file
//The contents are as follows

import Performance from `performance-report`
Performance({ 
  domain:`http://some.com/api` 
})複製程式碼
//Change webpack configuration

entry: {
    //add performance entry
    `performance`:path.resolve(__dirname, `../src/performance.js`),
},

//change htmlWebpackPlugin config like this
//Attention to dependence
new htmlWebpackPlugin({
    ...
    chunks: [`performance`,`vendors`,`main`],
    chunksSortMode: `manual`,
}),複製程式碼

框架使用

現在流行的nvvm框架都有自己的錯誤捕捉機制,因此不能直接使用window.onerror來捕獲異常。

解決方式:vue,react負責錯誤攔截、解析,呼叫外掛提供的方法插入到errorlist中進行上報

VUE使用方式

If you use the Vue framework, you can do it like this.

1、Introduce Performance
2、Copy the following code

import Performance from `performance-report`

Vue.config.errorHandler = function (err, vm, info) {
    let { message, stack } = err;

    // Processing error
    let resourceUrl,col,line;
    let errs = stack.match(/(.+?)/)
    if(errs&&errs.length) errs = errs[0]
    errs=errs.replace(/w.+js/g,$1=>{resourceUrl=$1;return ``;})
    errs=errs.split(`:`)
    if(errs&&errs.length>1)line=parseInt(errs[1]||0);col=parseInt(errs[2]||0)

    // Fixed parameters
    // Call the Performance.addError method
    Performance.addError({
      msg:message,
      col:col,
      line:line,
      resourceUrl:resourceUrl
    })
}複製程式碼

React使用方式

If you use the React framework, you can do it like this.

1、Introduce Performance

2、Error Handling in React 16.

If you don`t know Error Handling.Go to the official website to understand

reactjs.org/blog/2017/0…

react16之後提供Error Handling處理報錯機制,父元件新增componentDidCatch鉤子函式,父元件只能監聽子元件的異常資訊

//Top reference
import Performance from `performance-report`

//Parent component listens for subcomponent error information
componentDidCatch(error, info) {
    let {message,stack} = error  

    // Processing error
    let resourceUrl,col,line;
    let errs = stack.match(/(.+?)/)
    if(errs&&errs.length) errs = errs[0]
    errs=errs.replace(/w.+js/g,$1=>{resourceUrl=$1;return ``;})
    errs=errs.split(`:`)
    if(errs&&errs.length>1)line=parseInt(errs[1]||0);col=parseInt(errs[2]||0)

    // Fixed parameters
    // Call the Performance.addError method
    Performance.addError({
      msg:message,
      col:col,
      line:line,
      resourceUrl:resourceUrl
    })
}複製程式碼

引數說明:

完整呼叫方式

Performance({
    domain:`http://some.com/api`, 
    outtime:500,
    isPage:true,
    isResource:true,
    isError:true,
    filterUrl:[`http://localhost:35729/livereload.js?snipver=1`]
},(data)=>{
	fetch(`http://some.com/api`,{type:`POST`,body:JSON.stringify(result)}).then((data)=>{})
})複製程式碼
  • 同時傳入 domain和傳入的function ,function優先順序更高

  • domain :上報api介面

  • outtime :上報延遲時間,保證非同步資料的載入 (預設:1000ms)

  • isPage :是否上報頁面效能資料 (預設:true)

  • isResource :是否上報頁面資源效能資料 (預設:true)

  • isError :是否上報頁面錯誤資訊資料 (預設:true)

  • filterUrl :不需要上報的ajax請求 (例如開發模式下的livereload連結)

  • fn :自定義上報函式,上報方式可以用ajax可以用fetch (非必填:預設使用fetch)

對外方法:

一:addError :此方法向外掛中自定義上報錯誤資訊,vue,react,try{}catch 的報錯資訊均可採用此方法上報

案例:

let message = `js add error`
let col = 20
let line = 20
let resourceUrl = `http://www.xxx.com/01.js`

Performance.addError({
      msg:message,
      col:col,
      line:line,
      resourceUrl:resourceUrl
})複製程式碼

二:addData :上報時自定義的資料

案例:

Performance.addData((data)=>{
	data.name = `wangwei`
	data.some = {
		name:`wangwie`,
		age:20
	}
})複製程式碼

錯誤處理:

外掛會處理所有的error資訊並完成上報,錯誤處理分為4種型別

  • 1.圖片資源,js資源文字資源等資源錯誤資訊 n=`resource`
  • 2.js報錯,程式碼中的js報錯 n=`js`
  • 3.ajax請求錯誤 n=`ajax`
  • 4.fetch請求錯誤 n=`fetch`

AJAX處理:

  • AJAX分為 XMLHttpRequest 和 Fetch的處理
  • AJAX相容老闆般與新版本 例如:jq的1.x版本與2.x版本以上需要做相容處理
  • 攔截所有fetch請求資訊,遇到錯誤時收集並上報

所有資源資訊處理:

  • 上報所有資源資訊,資源型別以type來區分 type型別有
  • script:js指令碼資源
  • img:圖片資源
  • fetchrequest:fetch請求資源
  • xmlhttprequest:ajax請求資源
  • other :其他

執行方式:

git clone https://github.com/wangweianger/web-performance-report.git
npm install
//開發
npm run dev
//打包
npm run build

http://localhost:8080/test/ 頁面測試複製程式碼

單頁面程式處理說明:

  • 對於單頁面應用程式,只有第一次載入的頁面效能資料有效,之後的路由跳轉不會有頁面的效能資料,因為需要的靜態資源已經載入完成
  • 如果新的路由有ajax請求或者fetch請求,會抓取所有新的請求資料並上報。
  • 多頁面應用程式不會受影響

返回引數說明:

引數名 描述 說明
appVerfion 當前瀏覽器資訊
page 當前頁面
preUrl 上一頁面
errorList 錯誤資源列表資訊
->t 資源時間
->n 資源型別 resource,js,ajax,fetch,other
->msg 錯誤資訊
->method 資源請求方式 GET,POST
->data->resourceUrl 請求資源路徑
->data->col js錯誤行
->data->line js錯誤列
->data->status ajax錯誤狀態
->data->text ajax錯誤資訊
performance 頁面資源效能資料(單位均為毫秒)
->dnst DNS解析時間
->tcpt TCP建立時間
->wit 白屏時間
->domt dom渲染完成時間
->lodt 頁面onload時間
->radt 頁面準備時間
->rdit 頁面重定向時間
->uodt unload時間
->reqt request請求耗時
->andt 頁面解析dom耗時
resoruceList 頁面資源效能資料
->decodedBodySize 資源返回資料大小
->duration 資源耗時
->method 請求方式 GET,POST
->name 請求資源路徑
->nextHopProtocol http協議版本
->type 請求資源型別 script,img,fetchrequest,xmlhttprequest,other

一份完整的上報資料看起來像這樣:

{
  "page": "http://localhost:8080/test/", 
  "preUrl": "", 
  "appVersion": "5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36", 
  "errorList": [
    {
      "t": 1524050060518, 
      "n": "resource", 
      "msg": "img is load error", 
      "data": {
        "target": "img", 
        "type": "error", 
        "resourceUrl": "http://img1.imgtn.bd95510/"
      }, 
      "method": "GET"
    }, 
    {
      "t": 1524050060674, 
      "n": "js", 
      "msg": "ReferenceError: wangwei is not defined at http://localhost:8080/test/:73:15", 
      "data": {
        "resourceUrl": "http://localhost:8080/test/", 
        "line": 73, 
        "col": 15
      }, 
      "method": "GET"
    }, 
    {
      "t": 1524050060707, 
      "n": "ajax", 
      "msg": "ajax請求路徑有誤", 
      "data": {
        "resourceUrl": "http://mock-api.seosiwei.com/guest/home/api/shop/getHomeInitInf", 
        "text": "ajax請求路徑有誤", 
        "status": 0
      }, 
      "method": "GET"
    }, 
    {
      "t": 1524050060714, 
      "n": "fetch", 
      "msg": "fetch請求錯誤", 
      "data": {
        "resourceUrl": "http://mock-api.seosiwei.com/guest/order/api/order/getOrde", 
        "text": "TypeError: Failed to fetch", 
        "status": 0
      }, 
      "method": "POST"
    }
  ], 
  "performance": {
    "dnst": 0, 
    "tcpt": 1, 
    "wit": 17, 
    "domt": 165, 
    "lodt": 379, 
    "radt": 6, 
    "rdit": 0, 
    "uodt": 0, 
    "reqt": 16, 
    "andt": 210
  }, 
  "resourceList": [
    {
      "name": "http://localhost:8080/dist/performance-report.js", 
      "method": "GET", 
      "type": "script", 
      "duration": "71.60", 
      "decodedBodySize": 18592, 
      "nextHopProtocol": "http/1.1"
    }, 
    {
      "name": "https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js", 
      "method": "GET", 
      "type": "script", 
      "duration": "0.00", 
      "decodedBodySize": 0, 
      "nextHopProtocol": "h2"
    }, 
    {
      "name": "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=295864288,1887240069&fm=27&gp=0.jpg", 
      "method": "GET", 
      "type": "img", 
      "duration": "0.00", 
      "decodedBodySize": 0, 
      "nextHopProtocol": "http/1.1"
    }, 
    {
      "name": "http://localhost:35729/livereload.js?snipver=1", 
      "method": "GET", 
      "type": "script", 
      "duration": "149.20", 
      "decodedBodySize": 0, 
      "nextHopProtocol": "http/1.1"
    }, 
    {
      "name": "http://mock-api.seosiwei.com/guest/home/api/shop/getHomeInitInfo", 
      "method": "GET", 
      "type": "fetchrequest", 
      "duration": "38.30", 
      "decodedBodySize": 0, 
      "nextHopProtocol": "http/1.1"
    }, 
    {
      "name": "http://mock-api.seosiwei.com/guest/order/api/order/getOrder", 
      "method": "POST", 
      "type": "xmlhttprequest", 
      "duration": "42.30", 
      "decodedBodySize": 0, 
      "nextHopProtocol": "http/1.1"
    }
  ], 
  "addData": {
    "name": "wangwei", 
    "some": {
      "name": "wangwie", 
      "age": 20
    }
  }
}複製程式碼

原文地址:blog.seosiwei.com/detail/30

相關文章