performance-report页面性能、资源、错误、ajax,fetch请求上报插件 完善小巧

2,662 阅读6分钟

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->coljs错误行
->data->linejs错误列
->data->statusajax错误状态
->data->textajax错误信息
performance页面资源性能数据(单位均为毫秒)
->dnstDNS解析时间
->tcptTCP建立时间
->wit白屏时间
->domtdom渲染完成时间
->lodt页面onload时间
->radt页面准备时间
->rdit页面重定向时间
->uodtunload时间
->reqtrequest请求耗时
->andt页面解析dom耗时
resoruceList页面资源性能数据
->decodedBodySize资源返回数据大小
->duration资源耗时
->method请求方式GET,POST
->name请求资源路径
->nextHopProtocolhttp协议版本
->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