前端监控主要分成三个部分,数据采集、数据上报、数据存储。数据的采集又可以分为性能监控(常见性能指标、资源和接口的请求加载时间)、错误的收集、用户的行为。这一篇我们先来了解一下常见的性能指标。
性能指标
performance
performance.now()
performance.now() 方法返回一个精确到毫秒的时间戳,个别浏览器返回的时间戳没有被限制在一毫秒的精确度内,以浮点数的形式表示时间,精度最高可达微秒级,因此测试时如果需要比毫秒更高的精度,可以使用这个方法。
performance.now()返回的时间是距离Performance.timeOrigin(导航开始)的时间,Date.now()方法返回自 1970 年 1 月 1 日 00:00:00 (UTC) 到当前时间的毫秒数。
performance.now()方法的语义在level1和level2之间发生了变化。performance.now()方法过去是相对于导航计时规范中的performance.timing.navigationStart属性的。Performance. now()现在是相对于Performance.timeOrigin。
performance.timing.navigationStart
是基于浏览器的客户端时间戳,不依赖于服务器时间或其他外部时钟。然而,它仍然可能受到用户操作系统或浏览器中的时钟更改的影响,这可能导致不准确的时间戳。
Changes | Level 1 | Level 2 |
---|---|---|
Relative to | performance.timing.navigationStart |
Performance.timeOrigin |
Triggering conditions | Document fetch or unload prompt (if any) | Creation of the browsing context (if no prior document), unload prompt (if any), or start of the navigation (as defined in HTML, a few steps before fetch) |
performance.navigation
performance.navigation
对象提供了在指定的时间段里发生的操作相关信息,包括页面是加载还是刷新、发生了多少次重定向等。我们可以看看:
属性 | 含义 |
---|---|
type | 表示是如何导航到这个页面的 |
redirectCount | 表示在到达这个页面之前重定向了多少次 |
其中,type 的取值及含义如下表:
type的值 | 含义 |
---|---|
0 | 当前页面是通过点击链接,书签和表单提交,或者脚本操作,或者在url中直接输入地址 |
1 | 点击刷新页面按钮或者通过Location.reload()方法显示的页面 |
2 | 页面通过历史记录和前进后退访问时 |
255 | 任何其他方式 |
具体数据示例:
这个数据,主要是帮助我们看看页面重定向次数是否过多(能否减少重定向),页面访问的方式主要是怎样的,针对访问方式较多的场景我们能否做些优化。
performance.timing
window.performance.timing
里面有很多的性能相关的时间戳记录,我们来看一些常用的:
属性 | 含义 |
---|---|
navigationStart | 准备加载页面的起始时间,level2阶段使用的是performance.timeOrigin |
domainLookupStart | 开始进行dns查询的时间 如果使用了强缓存,就不需要dns解析,返回的便是fetchStart的时间 |
domainLookupEnd | dns查询结束的时间 |
connectStart | TCP连接开始 |
connectEnd | TCP连接完成 |
domInteractive | 解析dom树开始 |
domComplete | 解析dom树结束 |
domContentLoadedEventEnd | DOMContentLoaded事件完成 |
domContentLoadedEventStart | DOMContentLoaded事件启动之前的时间 |
loadEventEnd | onload事件结束的时间 |
fetchStart | 开始检查缓存或开始获取资源的时间 |
domLoading | loading的时间 (这个时候还木有开始解析文档) |
redirectStart | 第一个 HTTP 重定向开始时的时间戳,没有重 定向或者重定向中的不同源,这个值会是 0 |
redirectEnd | 最后一个 HTTP 重定向开始时的时间戳,没有 重定向或者重定向中的不同源,这个值会是 0 |
详情可见:Navigation Timing Level 2
性能指标
名称 | 公式 |
---|---|
DNS查询耗时 | domainLookupEnd - domainLookupStart |
TCP链接耗时 | connectEnd - connectStart |
request请求耗时 | responseEnd - responseStart |
解析dom树耗时 | domComplete - domInteractive |
白屏时间 | domloading - fetchStart |
domready时间 | domContentLoadedEventEnd - fetchStart |
onload时间 | loadEventEnd - fetchStart |
资源加载 | loadEventStart - domContentLoadedEventEnd |
- 白屏时间:页面开始显示内容的时间 。也就是:浏览器显示第一个字符或者元素的时间
-
首屏时间:用户打开网站开始,到浏览器首屏内容渲染完成的时间。对于用户体验来说,首屏时间是用户对一个网站的重要体验因素。
- HTML 加载完成时间
- 首屏图片加载完成时间
- 首屏接口完成加载完成时间
- 各资源耗时(主要统计css/js资源耗时)
- FP(首次绘制时间)
- FCP(首次内容渲染时间)
- onload时间
扩展
window.performance
API 是有缺点的,在 SPA 切换路由时,window.performance.timing
的数据不会更新。所以我们需要另想办法来统计切换路由到加载完成的时间。拿 Vue 举例,一个可行的办法就是切换路由时,在路由的全局前置守卫 beforeEach
里获取开始时间,在组件的 mounted
钩子里执行 vm.$nextTick
函数来获取组件的渲染完毕时间。
javascript
router.beforeEach((to, from, next) => {
store.commit('setPageLoadedStartTime', new Date())
})
mounted() {
this.$nextTick(() => {
this.$store.commit('setPageLoadedTime', new Date() - this.$store.state.pageLoadedStartTime)
})
}