读书笔记(十七):性能监控和错误收集

1.性能衡量指标

  • 首次绘制时间:页面发生第一次绘制的时间点。
  • 首次有内容绘制时间:指浏览器完成渲染DOM中第一部分内容(文本、图像或其他任何元素)的时间点,用户应该在视觉上有直观的感受。
  • 首次有意义绘制时间:指页面关键元素的渲染时间。
  • 首屏时间:进入页面之后,应用渲染完成整个屏幕(未滚动之前)内容的时间。
  • 用户可交互时间:用户可以与应用进行交互的时间。一般认为是DOMReady的时间。

DOMContentLoaded指的是文档中DOM内容加载完毕的时间,HTML结构已经是完整的了。Load事件是指页面的图片、字体、视频、音频等其他资源加载完毕后才会触发。

2.性能数据获取
window.performance API计算性能指标数据,还能计算出与页面资源加载和异步请求相关的数据。
调用window.performance.timing 会返回一个对象,包含各种页面加载和渲染的时间节点。

3.try…catch
这种方式需要开发者对预估存在错误风险的代码进行包裹,可以保证页面不崩溃,并对错误进行兜底处理。但是它无法处理语法错误和异步错误,只能处理运行时非异步错误,且对代码的侵入性强。

4.window.onerror
只需要给window添加onerror事件监听,同时注意将window.onerror放在所有脚本之前,便能对语法异常和运行异常进行处理。

window.onerror = function(message, source, lineno, colno, error) {
	//
}
  • message:错误信息提示。
  • source:错误脚本地址。
  • lineno:错误代码所在的行号。
  • colno:错误代码所在的列号。
  • error:错误的对象信息,比如,error.stack会获取错误的堆栈信息。

这种方式对代码入侵性较小,不必通过AST向代码中自动插入脚本。对语法错误和网络错误无能为力,需要显示返回true,以保证错误不会向上抛出,控制台也不会出现一堆错误提示信息。

5.错误处理

  • 跨域脚本的错误处理

对于不同域的js文件,window.onerror不能保证获取到有效信息,出于安全原因,不同浏览器返回的错误信息参数可能并不一致。比如:跨域之后,要统一返回脚本错误,就需要统一对script脚本进行如下设置。

crossorigin="anonymous"

同时要在服务器端添加Access-Control-Allow-Origin header内容以指定允许哪些域的请求访问。

  • promise的错误处理

提倡写promise的时候最后写上catch函数。

  • 网络加载错误处理

使用script标签、link标签进行脚本或其他资源加载,可能会由于某种原因(服务器错误,网络不稳定)导致脚本请求失败,网络加载错误,为了捕获异常:

<script src="" onerror="errorHandler(this)"></script>
<link rel="stylesheet" href="" onerror="errorHandler(this)">

也可以使用window.addEventListener(‘error’)方式对加载异常进行处理,但无法使用window.onerror处理,因为它是通过事件冒泡获取error信息的,网络加载错误是不会进行事件冒泡的(还有鼠标聚、失焦、移动、滚动)。

window.addEventListener('error', error => {
	//
}, true)

区分网络资源加载错误和其他一般错误:普通错误的error对象中会有message属性表示错误信息,资源加载错误没有。

  • 页面崩溃处理
window.addEventListener('load', () => {
	sessionStorage.setItem('good_exit', 'pending')
})

window.addEventListener('beforeunload', () => {
	sessionStorage.setItem('good_exit', 'true')
})

if (sessionStorage.getItem('good_exit') && sessionStorage.getItem('good_exit') !== 'true') {
	//
}
  • 框架错误处理

react在16之后使用componentDidCatch 来处理错误,Vue使用Vue.config.errorHandler来处理捕获到的错误;如果没有配置,框架会通过console.error的方式抛出错误,因此可以劫持来捕获框架中的错误并作出处理。

const nativeConsoleError = window.console.error
window.console.error = (...args) => nativeConsoleErrror.apply(this, [`I got ${args}`])

6.信息上报
数据上报域名往往与业务域名并不相同,好处有:

  • 使用单独域名,可以防止对主业务服务器造成压力,能够避免日志相关处理逻辑和数据在主业务服务器上的堆积。
  • 很多浏览器对同一个域名的请求量有并发数限制,单独域名能够充分利用现代浏览器的并发设置。

页面使用空的Image对象方式进行数据上报,原因是请求图片并不涉及跨域的问题。

let url = 'xxx?data=' + JSON.stringify(data)
let img = new Image()
img.src = url

你可能感兴趣的:(性能优化)