radar-js-analytic-sdk
v2.4.0
Published
很多产品线都有一些基础统计需求,如PV、UV、Click点击情况等。
Downloads
208
Readme
H5端 Radar Analytics SDK 集成文档(2023.9.5)
很多产品线都有一些基础统计需求,如PV、UV、Click点击情况等。
之前要使用公司的统计平台,需要先部署JS代码,再与数据计算组沟通打点地址、报表格式等需求,需要花费不少时间。不少产品线出于安全、稳定性的考虑,也不能使用第三方统计代码(如Google Analytics、神策、百度、sentry、友盟、火山引擎)。
现在,雷达分析平台将这类基础统计抽象出来,再加上奇舞团在CDN上托管的通用统计JS以及发布npm包,可以以非常低的成本获取产品基础统计报表。
更新说明:
重构内部函数:获取gid逻辑,限定只有浏览事件类型在gid最后一位是从1开始且自增,其他事件可以从0开始或保持当前数值,确保新老用户数统计结果准确性(本次更新)
取消优先调用概念,自动采集浏览事件支持需要的时候关闭或开启,无需重新调 getAutoTrack,该事件只需要在初始化的时候启用一次(2.3.0更新)
增加了对浏览事件的采集模式控制,分为手动模式和自动模式(2.2.6更新)
最新SDK版本号:2.4.0(2023.9.5)
使用
步骤:
注册并登录 https://radar.qihoo.net
创建应用并获取App Key
如果已创建的应用,请从 应用列表->设置 中查看App Key
说明:
- Radar支持多平台使用相同的App Key
如有疑问请联系: 谢丽姣 [email protected]
引入JS
在页面代码底部标签前,将JS代码粘贴过来,所有需要被统计的页面都要加(推荐使用动态语言的include、模板继承等方式来完成JS的全站引入)。
注: 如果页面还有其他统计,请将这段代码放在其他统计代码之前,尤其是Google统计。由于众所周知的原因,Google统计JS经常访问不到,如果咱们的统计JS在它之后,会很影响统计效果。
npm i radar-js-analytic-sdk --save
//全量压缩包,适用于web端、服务端
<script type="text/javascript" src="https://s.ssl.qhres2.com/pkg/radarsdk/radar-analytic-js-sdk-2.4.0.1693391976695.umd.js"></script>
通用使用方式:
<script>
// 原'优先调用'位置,新版取消此概念
RADAR_MONITOR.setProject('这里配置AppKey').getAutoTrack();
</script>
建议使用方式:
- 单页面/MPA应用
<script>
// 原'优先调用'位置,新版取消此概念
RADAR_MONITOR.setProject('这里配置AppKey');
</script>
- SPA应用
<script>
// 原'优先调用'位置,新版取消此概念
RADAR_MONITOR.setProject('这里配置AppKey').getAutoTrack();
</script>
接口说明:
初始化sdk
setProject(appKey, extend, options)
appKey: 表示项目代码(必须) extend: 全局自定义参数(可选) options: { trackForInit = true }(可选) trackForInit: 是否允许自动上报第一条浏览事件 初始化的过程中默认会产生一条页面浏览PV(版本大于2.2.0),可通过第三个参数关闭
- 版本在 2.2.0 以上会自动产生,不需要手动调用 getTrack 也能发起第一个PV
- 版本在 2.0.0 以上 & 2.2.0 以下需要初始化前调用 setManualPVEnable,再调用 getTrack才会产生PV
- 版本在 2.0.0 以下不会自动产生,也不存在 setManualPVEnable 这一方法,只需要调用 getTrack 就可以,上报次数不会限制
配置自动采集页面浏览事件模式
setDisableAutoPV(disable = true)
(在需要的时候暂时关闭或打开,新版无需优先调用)disable: 关闭自动采集'页面浏览事件'配置(全局) 参数值为 true 则关闭,默认配置打开 搭配 getAutoTrack 使用
- 默认该模式开启
- 如果自动采集模式全局配置为关闭,getAutoTrack 不生效
- 如果配置从关闭置为开启,无需重启 getAutoTrack,自动在下次事件发生时上报
配置手动采集页面浏览事件模式
目的是减少不必要的页面浏览条数产生,请业务自行检验是否仍需要开启。
setManualPVEnable(enable = true)
(在需要的时候暂时关闭或打开)enable: 打开手动采集'页面浏览事件'配置(全局) 参数值为 true 则开启,默认配置关闭 搭配 getTrack 使用
- 默认该模式关闭
- 如果手动采集模式全局配置为关闭,getTrack 不生效
- 如果置为开启,开启后每调用一次 getTrack 都会产生一条浏览事件的上报,为确保数据准确,请谨慎控制调用次数
自动发送页面浏览 PV/UV 统计
其原理是修改 window 对象的 pushState 和 replaceState 原生方法,在页面的 url 改变后自动采集页面浏览事件,若用户浏览器不支持这两种方法或者是使用 hash 的路由模式,则会监听 popstate 和 hashchange 事件来自动触发页面浏览事件。
getAutoTrack()
全局开启'页面浏览事件'自动采集模式时(默认开启),启用该统计则自动上报
手动发送页面浏览 PV/UV 统计
getTrack(options, extend, cookies)
options: { enableMenualOnce = false } // 如不需要,传null即可(可选) enableMenualOnce: 是否强制上报此次pv,仅本次生效,可不受全局配置影响 extend: 自定义拓展参数(可选) cookies: 用`,`拼接cookies
- 全局开启'页面浏览事件'手动采集模式后(默认关闭),不管 options 传什么,调用一次该接口即上报一条数据
- 与
RADAR_MONITOR.log(null, 'track')
是等效的,因此请注意检查是否因为多次调用导致产生不符合预期的条数
自动获取和发送点击统计
getClickAndKeydown()
默认关闭,调用则开启统计
配置会话时长
setActiveTime(time)
time: 默认会话时长30分钟
配置热力图功能
getClickHeatmap(times, minutes)
times: 满足点击次数上报 minutes: 等待时长(分钟)上报
自定义url字段
默认统计代码发送的页面 url 是当前页面地址去掉 ?、# 之后的内容,如果多个不同的 url 访问的是同一个页面。
setUrl(url)
url: 指定url,避免 IE 下设置 domain 后,读取 location.href 属性报权限错误,替换自动获取的页面地址
自定义title字段
setTitle(title)
title: 页面标题字符串,替换自动获取的页面标题
配置debug模式
setDebug(deb = true, appKey, extend, options)
deb: 开启debug模式(必须) appKey: 测试appkey(必须) extend: 自定义参数扩展(可选) options: { trackForInit = true }(可选) trackForInit: 是否允许自动上报第一条浏览事件
获取sdk版本信息
getLibVersion()
高级接口说明
配置PC端360浏览器设备ID接口
要在初始化 sdk 之前调用 asc、asc2、mid、m2 接口,以便传入参数。
步骤
- 先调用 setAscAndAsc2 接口,配置 asc 和 asc2 值
- 再调用 setThirdProps 接口,原业务使用 mid 则配置该参数,key 保持原来的 'mid'
- 再调用 setFourthProps 接口,原业务使用 m2 则配置该参数,key 保持原来的 'm2'
- 如果只调用 setAscAndAsc2 接口,sdk 默认会自动占位补充 mid、m2 在上报数据的第三位、第四位
- 如果只调用了 setAscAndAsc2 和 setThirdProps 接口,sdk默认会自动占位补充 m2 在上报数据的第四位
RADAR_MONITOR.setAscAndAsc2('11111','22222');
RADAR_MONITOR.setThirdProps("mid","33333");
RADAR_MONITOR.setFourthProps("m2","44444");
RADAR_MONITOR.setProject('QH_11_1552'); // 配置完后再初始化sdk
高级统计
针对视频、游戏类网站:由于统计代码中默认的会话时间是 30 分钟,超过 30 分钟未操作会被认为是两次会话,而视频、游戏类网站用户可能一直停留在页面上观看视频等操作,所以需要修改会话的默认时长,在原有代码后面加上 .setActiveTime(60)
即可,括号中的 60 单位是分钟,可以自行修改为其它值。
统计时长
对于一些需要统计时长类的场景,在 1.6.0 版中提供了时长类的打点,主要是利用心跳的机制由2个方法合作完成:beginHeartBeat(id, extend, timespan) 和 endHeartBeat(id, extend);
原理是当调用开始计时方法时,立即打一个点,然后每隔固定时间再打一个点以免异常退出时统计不到(当有异常退出时,至少时长能统计到上一个心跳);
当结束计时时或者捕捉到浏览器关闭事件时请调用 endHeartBeat 方法以结束时长的统计。
v2.3.0 以前的版本只支持一个计时器,v2.3.0 以后可多次调用 beginHeartBeat 和 endHeartBeat,同个计时器使用同个 id 开始和结束即可
/**
* 当需要开始计时的时候,调用 beginHeartBeat。
* 第1个参数为 ID,用来区分时长的;
* 如果一个参数满足不了,可以使用第2个参数再次扩展;
* 第3个参数为心跳间隔,单位为秒,最小为 5 秒,最长为 60 秒,默认为 10 秒。
*/
RADAR_MONITOR.beginHeartBeat('视频ID', {type: '电视剧', channel: 'baidu', sub_channel: 'baidu_tieba'}, 30);
/**
* 当要结束计时的时候,调用 endHeartBeat。
* 第1个参数为 ID;
* 第2个参数为扩展。
*/
RADAR_MONITOR.endHeartBeat('视频ID', {type: '电视剧', channel: 'baidu', sub_channel: 'baidu_tieba'});
自动获取和发送点击统计
通过调用 RADAR_MONITOR.getClickAndKeydown
方法,实现自动获取和发送点击统计。
适用元素类型为:submit、button、area、a、img。
某个元素若想传入自定义参数或者不上报,可以关闭在该元素中添加 bk="noupload",例如:
<a bk="noupload">...</a>
定义统计区域ID
针对点击统计,可以直接在 html 元素上定义要统计的 区域ID,如下:
<div bk="area1">...</div>
或
<div bk id="area2">...</div>
有"bk"属性("data-bk"同样可以)的容器内的点击,会带上 bk 定义的 区域ID。
如果 bk 的属性值未定义,取这个元素的 id,如果 id 也不存在,就忽略。
内置方法
获取采集数据接口
| 方法名 | 类型 | 返回 | 说明 | | :---------| :----------- | :----------- | :----------- | | RADAR_MONITOR.util.getReferrer() |-| 文本 | 返回document.referrer | RADAR_MONITOR.util.getBrowser() |-| 文本| 返回浏览器标识 | RADAR_MONITOR.util.getLocation() |-| 文本| 返回格式化后的location.href | RADAR_MONITOR.util.getGuid() |-| 文本| 返回当前用户唯一标识(已弃用) | RADAR_MONITOR.util.getMid() |-| 文本| 返回360浏览器内核设备ID | RADAR_MONITOR.util.getM2() |-| Promise<文本>| 返回360浏览器内核升级版设备ID | RADAR_MONITOR.util.getCount() |-| 文本| 返回当前用户24内访问次数 | RADAR_MONITOR.util.getFlashVer() |-| 文本| 返回Flash标识 | RADAR_MONITOR.util.getContainerId(el) |el,当前点击的元素| 文本| 返回当前点击元素的区域ID,优先取data-desc,其次id | RADAR_MONITOR.util.getText(el) |el,当前点击的元素| 文本| 返回当前点击元素的文本内容,优先取data-text,其次innerText | RADAR_MONITOR.util.getHref(el) |el,当前点击的元素| 文本| 返回当前点击A元素的链接地址,优先取data-href,其次href
注:每个方法的具体策略,请联系我们查看统计JS源码
常见使用场景
通过使用事件的全局开关,可避免事件的重复上报,以达到降低计算成本的目的,也可组合和重写上述方法的默认实现,以满足各种统计需求,有很好的灵活性和通用性。
下面介绍几种常见的应用场景:
页面浏览事件
sdk从2.1.2 (2023.2.20) 版本开始,提供自动和手动两种采集页面浏览PV/UV功能。
1、自动模式
自动模式在页面的 url 改变后自动采集页面浏览事件,查看触发原理。
- 如果自动模式同时产生两条及以上数据,则需要使用手动模式
- 该模式默认开启,但不代表启用采集,启动采集调 getAutoTrack
- 如果关闭,那么自动采集将停止,重新开启后无需再调 getAutoTrack
RADAR_MONITOR.getAutoTrack(); //启用自动采集
RADAR_MONITOR.setDisableAutoPV(); //关闭自动模式,则停止收集路由变化带来的浏览记录
2、手动模式
在页面切换的时候,手动调用 getTrack 来采集页面浏览PV事件,这个方法通常在页面 url 切换后调用。
// 比如现在是在 react 中可以在全局的 onUpdate 里来调用
onUpdate: function(){
RADAR_MONITOR.getTrack({ enableMenualOnce: true });
}
//vue 项目在路由切换的时候调用
router.afterEach((to,from) => {
Vue.nextTick(() => {
RADAR_MONITOR.getTrack({ enableMenualOnce: true });
});
});
注意: vue下因为首页打开时候就会默认触发页面更新,所以需要调用
RADAR_MONITOR.setDisableAutoPV()
,或者不要启用 getAutoTrack
扩展参数
如果默认的参数满足不了统计需求时,比如需要对页面访问的打点数据中增加一些自定义参数、对按钮点击的打点数据增加自定义参数,如与页面访问事件及点击事件无关的参数更推荐使用“自定义事件”进行收集上报。
初始时扩展
可以在 setProject 中的第2个参数为所有打点数据增加扩展参数,这样所有上报的数据中都会带上这些扩展的参数
RADAR_MONITOR.setProject('这里配置AppKey', {custom1: 'abc', custom2: '123', userid: 1234567});
全局扩展
1、可以用 extendBase 为所有打点数据增加扩展参数,可多次扩展,下次打点会带上这些参数
示例1:
//仅上报,扩展参数后同步调用页面访问上报接口
RADAR_MONITOR.extendBase({custom1: 'abc', custom2: '123', userid: 1234567}); //全局扩展
RADAR_MONITOR.getTrack({enableMenualOnce: true}); //无论手动上报配置是否开启,都会上报这条
示例2:
//开启手动上报,只需要在上报前开启一次即可
RADAR_MONITOR.extendBase({custom1: 'abc', custom2: '123', userid: 1234567}); //全局扩展
RADAR_MONITOR.setManualPVEnable(); //需要先开启手动上报页面访问配置
RADAR_MONITOR.getTrack(); //新版sdk默认直接无参数调用则无法上报
示例3:
//可通过页面访问上报时再次扩展
RADAR_MONITOR.extendBase({custom1: 'abc', custom2: '123', userid: 1234567}); //全局扩展
RADAR_MONITOR.getTrack(null, {channel: 'baidu', sub_channel: 'baidu_tieba'}); //这些参数不会扩展至全局
2、推荐,用 log 发送自定义事件打点,这样 p.htm 会带上这些自定义参数,因为根据 sdk 新策略,不推荐使用 getTrack 上报比较独立的参数
示例1:
//仅上报,扩展至全局后随即调用log接口
RADAR_MONITOR.extendBase({custom1: 'abc', custom2: '123', userid: 1234567});
RADAR_MONITOR.log(null, 'wpo');
示例2:
//可通过log再次扩展
RADAR_MONITOR.extendBase({custom1: 'abc', custom2: '123', userid: 1234567}); //全局扩展
RADAR_MONITOR.log({channel: 'baidu', sub_channel: 'baidu_tieba'}, 'wpo'); //这些参数不会扩展至全局
单次扩展
1、发送自定义事件
RADAR_MONITOR.log({channel: 'baidu', sub_channel: 'baidu_tieba'}, 'wpo');
2、在 getTrack 中的第1个参数,传入配置项 enableMenualOnce 为 true,可越过页面访问的全局开关配置,第2个参数为扩展参数
RADAR_MONITOR.getTrack({enableMenualOnce: true}, {channel: 'baidu', sub_channel: 'baidu_tieba'});
3、给点击元素扩展参数
document.addEventListener('click', (e) => {
RADAR_MONITOR.log({tag: e.target.tagName}, 'click');
}, false)
改变单项统计策略
如果要更改单项统计策略,可以通过改写对应的“获取数据”的方法来实现。
举例:在某些页面,要求“click统计”不统计点击元素的文本,而是统计元素的 className
实现如下:
var _getText = RADAR_MONITOR.util.getText(); //将原有方法备份,以便恢复
RADAR_MONITOR.util.getText = function(el) {
if(RADAR_MONITOR.util.getLocation().indexOf('/my/') > -1) { //当url中包含特殊字符串时
return el.className; //返回元素className;
}
return _getText(el); //否则,采用默认策略
};
禁用某种统计
如果某些页面不需要某种统计,可以调用对应的禁用方法。
禁用/启用Track统计
//禁用手动Track统计,此后调用 getTrack() 则不产生统计上报,默认禁用手动统计
RADAR_MONITOR.setManualPVEnable(false);
//启用手动 Track 统计,此后调用的 getTrack() 才会生效,每调一次 getTrack 产生一条上报记录
RADAR_MONITOR.setManualPVEnable(true);
禁用/启用AutoTrack统计
//禁用 AutoTrack 统计,此后调用 getAutoTrack() 也不会产生自动监听路由变化的访问统计上报
RADAR_MONITOR.setDisableAutoPV(true);
//启用 AutoTrack 统计,此后调用 getAutoTrack() 才会开启访问统计自动上报
RADAR_MONITOR.setDisableAutoPV(false);
发送自定义的点击统计
默认 click 统计只统计 a、button 等少数几种 tagName 上的点击。如果需要统计其他标签,例如 li 上的点击,可以发送自定义的点击统计。
举例:点击 li,发送 click 统计,实现如下:
document.querySelector('#container3').querySelectorAll('li').forEach(el => {
el.addEventListener('click', (e) => {
var target = e.target;
var params = {
cId : RADAR_MONITOR.util.getContainerId(target), //事件名称组名
c : RADAR_MONITOR.util.getText(target) //事件名称
};
RADAR_MONITOR.log(params, 'click'); //发送点击统计
}, false)
})
发送完全自定义统计
利用底层的 RADAR_MONITOR.log 方法,可以发送完全自定义的统计信息。
举例:发送页面 domReady 和 window.onload 时间,实现如下:
首先,在页面尽可能早的插入以下代码:
<script>var G_start_time = new Date;</script>//记录页面开始加载的时间
然后,收集时间并发送请求:
var G_ready_time;
document.addEventListener('DOMContentLoaded', function(){
G_ready_time = new Date; //记录页面domReady的时间
}, false);
RADAR_MONITOR.setConf("wpoUrl", "http://s.360.cn/yunpan/perform.html"); //定义'wpo'类型统计的接收URL
window.onload = function(){
var params = {
t0 : G_ready_time - G_start_time,
t1 : new Date - G_start_time
};
RADAR_MONITOR.log(params, 'wpo'); //发送'wpo'类型统计
}
页面有其他名为 RADAR_MONITOR 的统计
本统计在 window 下定义的变量名为 RADAR_MONITOR,大部分情况下,原页面不会有 RADAR_MONITOR 这个变量,就算有,造成的后果也只是本统计无法使用。
如果页面上已有 RADAR_MONITOR 变量,本统计不会破坏原有的 RADAR_MONITOR,这时,需要用下面的方法使用本统计:
<script>
(function(m) {
m.setProject('这里配置AppKey').getClickAndKeydown().getClickHeatmap(10, 1).setActiveTime(60);
})(RADAR_MONITOR);
</script>
打点参数说明
Track 统计
默认发送以下参数:
| 参数 | 说明 | 示例 | | :---------| :----------- | :----------- | | u | 当前页面地址 |http://yunpan.360.cn | gid |前三位为当前用户唯一ID,最后一位为浏览事件累计自增数,倒数第二位为本次访问的开始时间|233721054.382655244.1457698147282.1478749461964.8717| | mid | 360浏览器内核设备ID |7416457303e7f7baf7cc65a12f651468| | m2 | 360浏览器内核升级设备ID |203f1440d70ae40839826aa5a1185bd8| | sid | 当前会话ID,最后一组为本次会话中访问次数计数器。会话默认为30分钟,可以通过setActiveTime来修改 |233721054.2725755090674145300.1478748424279.6074| | p | 项目代号,在开发者信息管理平台中注册网站时自动分配 |QH_1_7| | title | 网页标题 |Web开发者使用指南| | b | 用户浏览器 |Firefox| | q | 搜索关键词 |360官网| | eqid | 百度搜索ID |fe3cbe5b000188f60000000361e4e4f7| | c | 24小时内用户访问次数 |21| | r | 页面来源(Referrer)|http://yunpan.360.cn/my | fl | Flash版本(-1表示没安装)|11| | sd | 屏幕颜色 |24-bit| | sr | 分辨率 |1920x1080| | ul | 浏览器语言 |en-us| | uc | 特定的 cookie |think_locale%3Den%26stc_ls%3DRRzz| | ce | 是否支持 cookie | 1 | | t | 时间戳,无意义,避免浏览器缓存 | 1332742970052 | | asc | 360浏览器内核加密设备ID |7416457303e7f7baf7cc65a12f651468.1006.1669615205000| | asc2 | 360浏览器内核加密升级设备ID |7416457303e7f7baf7cc65a12f651468ddsawf341qaz.11ea.1669615205000|
Click 统计
默认发送以下参数:
| 参数 | 说明 | 示例 | | :---------| :----------- | :----------- | | u | 当前页面地址 |http://yunpan.360.cn | gid |前三位为当前用户唯一ID,最后一位为浏览事件累计自增数,倒数第二位为本次访问的开始时间|233721054.382655244.1457698147282.1478749461964.8717| | sid | 当前会话ID,最后一组为本次会话中访问次数计数器。会话默认为30分钟,可以通过setActiveTime来修改 |233721054.2725755090674145300.1478748424279.6074| | p | 项目代号,在开发者信息管理平台中注册网站时自动分配 |QH_1_7| | title | 网页标题 |Web开发者使用指南| | f | 链接去向 |http://yunpan.360.cn/index/download/ | c | 被点击元素的内容 |下载| | cId | 点击区域ID,用于归并区域内的点击 |container| | t | 时间戳,无意义,避免浏览器缓存 | 1332742970052 |
热力图统计
默认发送以下参数:
| 参数 | 说明 | 示例 | | :---------| :----------- | :----------- | | u | 当前页面地址 |http://yunpan.360.cn | gid |前三位为当前用户唯一ID,最后一位为浏览事件累计自增数,倒数第二位为本次访问的开始时间|233721054.382655244.1457698147282.1478749461964.8717| | sid | 当前会话ID,最后一组为本次会话中访问次数计数器。会话默认为30分钟,可以通过setActiveTime来修改 |233721054.2725755090674145300.1478748424279.6074| | p | 项目代号,在开发者信息管理平台中注册网站时自动分配 |QH_1_7| | title | 网页标题 |Web开发者使用指南| | sr | 分辨率 |1920x1080| | pos | 鼠标位置 |750.448,750.448,541.453,541.453,541.453,637.454,684.452,951.460,951.460,951.460 多个之间用逗号隔开,x 和 y 值之间用 . 号隔开| | t | 时间戳,无意义,避免浏览器缓存 | 1332742970052 |
时长统计
默认发送以下参数:
| 参数 | 说明 | 示例 | | :---------| :----------- | :----------- | | u | 当前页面地址 |http://yunpan.360.cn | gid |前三位为当前用户唯一ID,最后一位为浏览事件累计自增数,倒数第二位为本次访问的开始时间|233721054.382655244.1457698147282.1478749461964.8717| | sid | 当前会话ID,最后一组为本次会话中访问次数计数器。会话默认为30分钟,可以通过setActiveTime来修改 |233721054.2725755090674145300.1478748424279.6074| | p | 项目代号,在开发者信息管理平台中注册网站时自动分配 |QH_1_7| | title | 网页标题 |Web开发者使用指南| | id | 第1个参数ID的值 |123456| | steptime | 距离上次已经过的时长,单位为秒 |15| | t | 时间戳,无意义,避免浏览器缓存 | 1332742970052 |
过滤搜索引擎蜘蛛
sdk会过滤搜索引擎蜘蛛触发的事件,使用UserAgent里包含的特殊字符串来识别(不区分大小写)。
以下是过滤特殊字符串:
const spiderList = [
"Baiduspider",
"Googlebot",
"360Spider",
"Sosospider",
"Yahoo! Slurp China",
"Yahoo!",
"YoudaoBot",
"YodaoBot",
"Sogou web spider",
"Sogou inst spider",
"Sogou spider2",
"Sogou blog",
"Sogou News Spider",
"Sogou Orion spider",
"msnbot",
"msnbot-media",
"bingbot",
"bingpreview",
"YisouSpider",
"ia_archiver",
"EasouSpider",
"JikeSpider",
"Bytespider"
]
Radar Analytics JS SDK:exception 集成文档(2022.05.27)
JS异常捕获插件
JS异常捕获大多是对web页面上问题进行捕获的,sdk自动捕获的异常类型的有以下几个:
- Uncaught ReferenceError:引用错误
- RangeError:范围错误
- TypeError:类型错误
- URIError:URL错误
- ResourseError:资源错误(img、video、audio、script、source、link)
- Promise:reject异常
- 异步回调异常:函数或对象undefined
- script文件加载失败
- EvalError: eval()异常
支持SPA框架:Vue和React语言框架。
集成步骤:
本功能是基于radar-analytic-js-sdk的插件功能实现的。
集成步骤如下:
1、需要检查下本地是否已经集成了radar-analytic-js-sdk
2、下载npm包
npm install radar-analytic-js-capture-exception --save-dev
3、初始化插件,并开启自动捕获异常
import RADAR_MONITOR from "radar-js-analytic-sdk";
import "radar-analytic-js-capture-exception";
var exception = RADAR_MONITOR.use('exception', {
isOpenHttpServer: true, //是否开启异常网络捕获。默认是开启
whiteUrls: ['http://abc.com','http://localhost/test-api.js'] //无需上报捕获的异常网络请求
});
exception是插件对象, 用来调用实例化方法。
接口说明:
自定义上报异常错误对象
captureException(exception)
@param {Error} exception Error类型对象
例如:
var error = new Error('test exception'); exception.captureException(error);
自定义上报错误事件
captureEvent(type, stacktrace, message, name)
@param {String} type 错误类型 @param {String} stacktrace 堆栈信息 @param {String} message 自定义消息 @param {String} name 自定义名称
例如:
var type = "error"; var stacktrace = ""; var message = "this is a message"; var name = "abc"; exception.captureEvent(type, stacktrace, message, name);
打点参数说明
每次发生异常情况后,发送数据。
默认发送以下参数:
| 参数 | 说明 | 示例 | | :---------| :----------- | :----------- | | u | 当前页面地址 |http://yunpan.360.cn | gid |前三位为当前用户唯一ID,最后一位为浏览事件累计自增数,倒数第二位为本次访问的开始时间|233721054.382655244.1457698147282.1478749461964.8717| | sid | 当前会话ID,最后一组为本次会话中访问次数计数器。会话默认为30分钟,可以通过setActiveTime来修改 |233721054.2725755090674145300.1478748424279.6074| | p | 项目代号,在开发者信息管理平台中注册网站时自动分配 |QH_1_7| | title | 网页标题 |Web开发者使用指南| | mid | 第1个参数ID的值 |123456| | t | 时间戳,无意义,避免浏览器缓存 | 1332742970052 | | type| 错误类型 |ReferenceError| | stacktrace| 异常错误堆栈信息 |ReferenceError: a is not defined ...| | message| 错误消息 |Uncaught ReferenceError: a is not defined | | name| 自定义错误名称 |custom|
Radar Analytics JS SDK:exposure 集成文档(2022.04.29)
元素曝光pv打点插件
本功能是基于radar-analytic-js-sdk的插件功能实现的。
每次页面展示的元素,需要某个元素曝光后,获取元素属性的数据功能。
该功能使用插件方式集成,集成步骤如下:
1、集成第三方库IntersectionObserver,w3c官方提供了polyfill,兼容了主流浏览器版本
npm install intersection-observer --save-dev
2、集成插件
npm i radar-analytic-js-exposure
或
<script src="https://s3.ssl.qhres2.com/!a1ad9a60/radar-analytic-js-exposure.umd.js"></script>
3、初始化插件
import RADAR_MONITOR from "radar-js-analytic-sdk";
import "radar-analytic-js-exposure";
var expose = RADAR_MONITOR.use('exposure', '');
expose是插件对象, 用来调用实例化方法。
4、注册曝光元素
expose.observe(element);
5、配置元素上报事件名称
设置自定义属性:bk-expose,示例如下:
<div class="container">
<div id="bk1000" bk-expose="商品1">第一件商品</div>
<div id="bk1000" bk-expose="商品2">第二件商品</div>
</div>
<div class="container" >
<div>
<div bk-expose="商品3">第三件商品</div>
<div bk-expose="商品4">第四件商品</div>
</div>
</div>
js-classname实现获取元素方式:
var elements = document.getElementsByClassName('container');
console.log("注册元素:",elements);
for (const el in elements) {
if (Object.hasOwnProperty.call(elements, el)) {
const element = elements[el];
expose.observe(element);
}
}
或者使用document.getElementById来获取元素
打点参数说明
每次曝光指定元素后,发送数据。
默认发送以下参数:
| 参数 | 说明 | 示例 | | :---------| :----------- | :----------- | | u | 当前页面地址 |http://yunpan.360.cn | gid |前三位为当前用户唯一ID,最后一位为浏览事件累计自增数,倒数第二位为本次访问的开始时间|233721054.382655244.1457698147282.1478749461964.8717| | sid | 当前会话ID,最后一组为本次会话中访问次数计数器。会话默认为30分钟,可以通过setActiveTime来修改 |233721054.2725755090674145300.1478748424279.6074| | p | 项目代号,在开发者信息管理平台中注册网站时自动分配 |QH_1_7| | title | 网页标题 |Web开发者使用指南| | mid | 第1个参数ID的值 |123456| | t | 时间戳,无意义,避免浏览器缓存 | 1332742970052 | | c| 获取bk-expose属性值 |bk-expose="商品1"|
Radar Analytics JS SDK:performance 集成文档(2022.07.08)
性能监测插件
本功能是基于radar-analytic-js-sdk的插件功能实现的,对页面进行性能方面的指标采集,目前正在快速迭代中。
SDK接入
NPM
npm是JavaScript 的包管理工具,可以安装、共享、分发代码,管理项目依赖关系,关于npm的安装和使用可以参考官方文档。
npm i radar-analytic-performance
import RADAR_MONITOR from "radar-js-analytic-sdk";
import "radar-analytic-performance";
//初始化sdk
RADAR_MONITOR.setProject("QH_11_1552");
//初始化性能监测和配置各个指标开启,默认指标采集是true。
RADAR_MONITOR.use("performance", {
clsEnable: true,
fidEnable: true,
lcpEnable: true,
fcpEnable: true,
ttfbEnable: true,
fpEnable: true,
navigation_timingEnable: true,
ttiEnable: true
});
验证上报
使用Chrome DevTools验证上报
打开Chrome DevTools,选择 Networks,查看 Request Method 为 GET 的请求, 上报域名为: http://s.360.cn/qdas/p.htm
打点参数说明
| 参数 | 说明 | 示例 | | :---------| :----------- | :----------- | | u | 当前页面地址 |http://yunpan.360.cn | gid |前三位为当前用户唯一ID,最后一位为浏览事件累计自增数,倒数第二位为本次访问的开始时间|233721054.382655244.1457698147282.1478749461964.8717| | sid | 当前会话ID,最后一组为本次会话中访问次数计数器。会话默认为30分钟,可以通过setActiveTime来修改 |233721054.2725755090674145300.1478748424279.6074| | p | 项目代号,在开发者信息管理平台中注册网站时自动分配 |QH_1_7| | title | 网页标题 |Web开发者使用指南| | mid | 第1个参数ID的值 |123456| | t | 时间戳,无意义,避免浏览器缓存 | 1332742970052 | | _indicators| 性能指标 | cls、fcp、fid、ttfb、lcp、navigation_timing、tti | | _value | 指标值 | 31.100000000093132 | | isCustom | 是否为自定义指标 | false |
性能指标
如何计算 TTI 指标
该指标有助于识别看起来具备交互性但实际上并非如此的页面情况。迅捷的TTI有助于确保页面的有效性。
本文指标介绍部分引用自 https://web.dev/tti/
什么是 TTI 指标
TTI(Time To Interactive),即从页面加载开始到页面处于完全可交互状态所花费的时间。
页面处于完全可交互状态时,满足以下3个条件:
- 页面已经显示有用内容
- 页面上的可见元素关联的事件响应函数已经完全注册
- 事件响应函数可以在事件发生后的50ms内开始执行
很多情况下,开发者往往只关注页面渲染相关的指标,如FP、FCP等,而忽视了页面的可用性指标。
TTI即是反应页面可用性的重要指标,TTI值越小,代表用户可以更早地操作页面,用户体验就更好。
如何获取TTI指标
用户访问Web页面,通常会有两种模式:
直接通过服务端路由切换的同步跳转场景
通过客户端路由跳转的SPA页面切换场景
算法描述
Long Task定义:在浏览器主线程执行时间超过50ms的Task。
静默窗口定义:窗口所对应的时间内没有Long Task,且进行中的网络请求数不超过2个。
- 从起始点(一般选择FCP或FMP)时间开始,向前搜索一个不小于5s的静默窗口期。
- 找到静默窗口期后,从静默窗口期向后搜索到最近的一个Long Task,Long Task的结束时间即为TTI
- 如果没有找到Long Task,以起始点时间作为TTI
- 如果2、3步骤得到的TTI < DOMContentLoadedEventEnd,以DOMContentLoadedEventEnd作为TTI
参考如下示意图(图中的First Consistently Interactive 即为TTI):
浏览器兼容性说明
TTI指标要求浏览器支持Long Tasks API和Resource Timing API。
如何优化TTI指标
如需了解如何改进某个特定网站的TTI,您可以运行一次Lighthouse性能审计,并留心查看审计建议的各种具体机会。
如需了解改进TTI的常见方式(针对任何网站),请参阅以下性能指南:
- 优化:缩小JavaScript体积
- 优化:预链接到所需的来源
- 优化:预加载关键请求
- 优化:减少第三方代码的影响
- 优化:最小化关键请求深度
- 优化:减少JavaScript执行时间
- 优化:最小化主线程工作
- 优化:保持较低的请求数和较小的传输大小
参考资料
如何计算 Navigation Timing 指标
它提供了可用于衡量一个网站性能的数据,与用于相同目的的其他基于JavaScript的机制不同,它可以提供更有用和更准确的端到端延迟数据。
你可以衡量之前难以获取的数据,如卸载前一个页面的时间,在域名解析上的时间,在执行load(en-US)事件处理器上花费的总时间等。
各字段解释
初始化阶段
- redirectStart:页面重定向时的开始时间(如果存在重定向的话)或者是0
- redirectEnd:如果存在重定向的话,redirectEnd表示最后一次重定向后服务端response的数据被接收完毕的时间。否则的话就是0
请求阶段
- fetchStart:浏览器发起资源请求时,如果有缓存,则返回读取缓存的开始时间
- domainLookupStart:查询DNS的开始时间。如果请求没有发起DNS请求,如keep-alive,缓存等,则返回fetchStart的时间点
- domainLookupEnd:查询DNS的结束时间。如果没有发起DNS请求,如keep-alive,缓存等,则返回fetchStart的时间点
- connectStart:当浏览器开始与服务器连接时的时间。如果没有建立连接,如请求是keep-alive、缓存等,那么它的值等同于domainLookupEnd
- secureConnectionStart:如果页面使用HTTPS,它的值是安全链接握手之前的时刻。如果该属性不可用,则返回undefined。如果该属性可用,但没有使用HTTPS,则返回0
- connectEnd:当浏览器端完成与服务端建立连接的时刻。如果没有建立连接,如请求是keep-alive、缓存等,那么它的值等同于domainLookupEnd
- responseStart:指客户端收到从服务端(或缓存、本地资源)相应回的第一个字节的数据时刻
- responseEnd:指客户端收到服务端(或缓存、本地资源)响应回的最后一个字节的数据时刻
解析渲染阶段
- domInteractive:浏览器完成对所有HTML的解析并且DOM构建完成的时间点,是DOM准备就绪的时间点
- domContentLoaded:DOM准备就绪并且没有样式表阻止JavaScript执行的时间点,可以开始构建渲染树,一般表示DOM和CSSOM均准备就绪的时间点
- domComplete:顾名思义,所有处理完成,并且网页上的所有资源(图像等)都已下载完毕,也就是说,加载转环已停止旋转,表示网页及其所有子资源都准备就绪的时间点
- loadEventStart:作为每个网页加载的最后一步,浏览器回触发
onload
事件,以便触发额外的应用逻辑 - loadEventEnd:onload事件执行完成
许多JavaScript框架都会等待onload
事件发生后,才开始执行它们自己的逻辑,因此,浏览器会捕获loadEventStart
和loadEventEnd
时间戳,让我们能够追踪执行所花费的时间。
各阶段计算公式
经过上面各个字段的解释,可以清晰得出以下:
Redirect:redirectEnd - redirectStart
计算条件:redirectEnd非0且redirectStart非0
DNS:domainLookupEnd - domainLookupStart
计算条件:domainLookupEnd非0且domainLookupStart非0
TCP:connectEnd - connectStart
计算条件:connectEnd非0且connectStart非0
SSL:connectEnd - secureConnectionStart
计算条件:connectEnd非0且secureConnectionStart非0
Request:responseStart - requestStart
计算条件:responseStart非0且requestStart非0
Response:responseEnd - responseStart
计算条件:responseEnd非0且responseStart非0
DomReady:domContentLoaded - fetchStart
计算条件:domContentLoaded非0且fetchStart非0
DomParse:domInteractive - responseEnd
计算条件:domInteractive非0且responseEnd非0
resourceLoad:loadEventStart - domContentLoaded
计算条件:loadEventStart非0且domContentLoaded非0
参考资料
如何计算 FP 和 FCP 指标
FP(First Paint)
首次渲染的时间点。
在性能统计指标中,从用户开始访问 Web 页面的时间点到 FP 的时间点这段时间可以被视为 白屏时间,也就是说在用户访问 Web 网页的过程中,FP 时间点之前,用户看到的都是没有任何内容的白色屏幕,用户在这个阶段感知不到任何有效的工作在进行,所以通常会反映页面的白屏时间,而白屏时间会反映当前 Web 页面的网络加载性能情况,当加载性能非常良好的情况下,白屏的时间就会越短,用户等待内容的时间就会越短,流失的概率就会降低。
FCP(First Contentful Paint)
首次有内容渲染的时间点。
在性能统计指标中,从用户开始访问 Web 页面的时间点到 FCP 的时间点这段时间可以被视为 无内容时间,也就是说在用户访问 Web 网页的过程中,FCP 时间点之前,用户看到的都是没有任何实际内容的屏幕,用户在这个阶段获取不到任何有用的信息,所以通常会反映页面的首次出现内容的时间,而首次出现内容时间会反映当前 Web 页面的网络加载性能情况、页面 DOM 结构复杂度情况、inline script 的执行效率的情况,当所有的阶段性能做的非常好的情况下,首次出现内容的时间就会越短,用户等待的时间就会越短,流失的概率就会降低 首次内容绘制 (FCP) 指标测量页面从开始加载到页面内容的任何部分在屏幕上完成渲染的时间。
对于该指标,"内容"指的是文本、图像(包括背景图像)、<svg>元素或非白色的<canvas>元素。
FP与FCP这两个指标之间的主要区别是:FP是当浏览器开始绘制内容到屏幕上的时候,只要在视觉上开始发生变化,无论是什么内容触发的视觉变化,在这一刻,这个时间点,叫做FP。
相比之下,FCP指的是浏览器首次绘制来自DOM的内容,例如:文本,图片,SVG,canvas元素等,这个时间点叫FCP。
怎样算是良好的 FCP 分数
为了提供良好的用户体验,网站应该努力将首次内容绘制推荐时间控制在1.8 秒或以内。
为了确保您能够在大部分用户的访问期间达成建议目标值,一个良好的测量阈值为页面加载的第 75 个百分位数,且该阈值同时适用于移动和桌面设备。
如何获取指标
通过 W3C Paint Timing 规范草案 中的描述, PerformancePaintTiming 中包含当前 Web 页面的绘制性能打点信息,可通过 performance.getEntriesByType('paint') 方法获取, FP和 FCP 就在其中。
- 找到 name 为 first-paint 的对象,描述的即为 FP 的指标数据,其中 startTime 即为 FP 时间,如下图所示:
- 找到 name 为 first-contentful-paint 的对象,描述的即为 FCP 的指标数据,其中 startTime 即为 FCP 时间,如下图所示:
浏览器兼容性说明
指标要求浏览器支持 Paint Timing API。
如何优化FCP指标
- 优化:消除阻塞资源
- 优化:缩小 CSS
- 优化:移除未使用的CSS
- 优化:预连接到所需的来源
- 优化:减少服务端响应时间(TTFB)
- 优化:避免多个页面重定向
- 优化:预加载关键请求
- 优化:避免巨大的网络负载
- 优化:如何使用高效缓存策略去缓存静态资源
- 优化:避免 DOM 过大
- 优化:最小化关键请求深度
- 优化:确保文本在网页字体加载期间保持可见
- 优化:保持较少的请求数以及较小的传输大小
参考文章
如何计算LCP指标
最大内容绘制 (LCP) 是测量感知加载速度的一个以用户为中心的重要指标,因为该项指标会在页面的主要内容基本加载完成时,在页面加载时间轴中标记出相应的点,迅捷的 LCP 有助于让用户确信页面是有效的。
本文指标解释的内容引用自 https://web.dev/lcp
指标解释
LCP(Largest Contentful Paint )
最大内容绘制 (LCP) 指标会根据页面首次开始加载的时间点来报告可视区域内可见的最大图像或文本块完成渲染的相对时间。
哪些元素在考量范围内
根据当前最大内容绘制 API中的规定,最大内容绘制考量的元素类型为:
- <img>元素
- 内嵌在<svg>元素内的<image>元素
- <video>元素(使用封面图像)
- 通过url()函数(而非使用CSS 渐变)加载的带有背景图像的元素
- 包含文本节点或其他行内级文本元素子元素的块级元素
何时报告最大内容绘制
Web页面通常是分阶段加载的,因此,页面上最大的元素可能会发生变化。
例如,在一个带有文本和图像的页面上,浏览器最初可能只是呈现文本,而此时浏览器会分派一个largest-contentful-paint entry,稍后,图像完成加载完成,会分派第二个largest-contentful-paint entry。
web.dev 给出的推荐时间是 2500ms,可以根据您站点的自身特性来适当调整。
指标获取实现细节
创建一个 PerformanceObserver ,使用 Largest Contentful Paint API 监听并上报。具体的结算时机可以参考下文的代码实现:
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('LCP candidate:', entry.startTime, entry);
}})
.observe({type: 'largest-contentful-paint', buffered: true});
浏览器兼容性说明
指标要求浏览器支持 Largest Contentful Paint API 和 PerformanceObserver,sdk引用polyfill来支持chrome、Firfox、Safari浏览器,理论上也可能支持chrome内核浏览器。
如何优化LCP指标
LCP主要受四个因素影响:
- 缓慢的服务器响应速度
- JavaScript 和 CSS 渲染阻塞
- 资源加载时间
- 客户端渲染
如需深入了解如何改进LCP,请参阅优化LCP。
有关其他能够改进LCP的单个性能技巧的进一步指导,请参阅:
- 使用PRPL模式做到即时加载
- 优化关键渲染路径
- 优化您的CSS
- 优化您的图像
- 优化网页字体
- 优化您的JavaScript(针对客户端渲染的网站)
- 优化:使用 PRPL 模式做到即时加载
- 缩小 JavaScript 体积
- 优化:减少 JavaScript 执行时间
- Reduce JavaScript payloads with code splitting
- 优化:移除未使用的代码
- Minify and compress network payloads
- Serve modern code to modern browsers for faster page loads
- Publish, ship, and install modern JavaScript for faster applications
- How CommonJS is making your bundles larger
其他资源
安妮·沙利文 (Annie Sullivan)在performance.now()上发表的演讲:
- 《从 Chrome 的性能监测工具中吸取的教训》(2019)
如何计算CLS指标
重要词汇: 累积布局偏移 (CLS) 是测量视觉稳定性的一个以用户为中心的重要指标,因为该项指标有助于量化用户经历意外布局偏移的频率,较低的 CLS 有助于确保一个页面是令人愉悦的。
本文指标解释的内容引用自 https://web.dev/cls
CLS指标介绍(Cumulative Layout Shift)
CLS 测量整个页面生命周期内发生的所有意外布局偏移中最大一连串的布局偏移分数。
每当一个可见元素的位置从一个已渲染帧变更到下一个已渲染帧时,就发生了布局偏移 。(有关单次布局偏移分数计算方式的详细信息,请参阅下文。)
CLS 分数如何计算
浏览器在计算分布偏移分数时,会查看可视区域大小和两个已渲染帧之间的可视区域中不稳定元素的位移。布局偏移分数是该位移的两个度量的乘积:影响分数和距离分数(两者定义如下):
布局偏移分数 = 影响分数 * 距离分数
影响分数
影响分数测量不稳定元素对两帧之间的可视区域产生的影响。
前一帧和当前帧的所有不稳定元素的可见区域集合(占总可视区域的部分)就是当前帧的影响分数。
在上图中,有一个元素在一帧中占据了一半的可视区域。接着,在下一帧中,元素下移了可视区域高度的25%。红色虚线矩形框表示两帧中元素的可见区域集合,在本示例中,该集合占总可视区域的75%,因此其影响分数为0.75。
距离分数
布局偏移分数计算公式的另一部测量不稳定元素相对于可视区域位移的距离。
距离分数指的是任何不稳定元素在一帧中位移的最大距离(水平或垂直)除以可视区域的最大尺寸维度(宽度或高度,以较大者为准)。
在上方的示例中,最大的可视区域尺寸维度是高度,不稳定元素的位移距离为可视区域的25%,因此距离分数为0.25,所以,在这个示例中,影响分数是0.75,距离分数是0.25,所欲布局偏移分数是0.75*0.25=0.1875。
最初,布局偏移分数只根据影响分数进行计算。引入距离分数是为了避免在大元素发生微小位移的情况下进行过度惩罚的情况。
预期布局偏移 vs 意外布局偏移
布局偏移并不总是坏事,事实上,许多动态网络应用程序经常更改页面元素的起始位置。
由用户发起的布局偏移
布局偏移只有在用户并不期望其发生时才算是坏事,换言之,对用户交互(单击链接、点选按钮、在搜索框中键入信息等)进行响应的布局偏移通常没有问题,前提是偏移发生的时机与交互时机足够接近,使用户对前后关系一目了然。
例如,如果某次用户交互触发了一个网路请求,而该请求可能需要一段时间才能完成,那么最好立即留出一些空间并显示加载指示器,避免在请求完成时出现令用户不快的布局偏移。如果用户没有意识到当前正在加载某些内容。或者不知道资源什么时候能够准备就绪。他们就可能会在等待期间尝试点击其他内容(来打破僵局)。
在用户输入500毫秒内发生的布局偏移会带有hadRecentInput标志,便于在计算中排出这些偏移。
小心: hadRecentInput标志仅适用于不连续输入事件,如轻触、点击或按键操作。滚动、拖动或捏拉缩放手势等连续性交互操作不算作"最近输入"。更多详情请参阅布局不稳定性规范。
怎样算才是良好的CLS分数
为了提供良好的用户体验,网站应该努力将CLS分数控制在0.1或以下。为了确保您能够在大部分用户的访问期间达成建议目标值,一个良好的测量阈值为页面加载的第75个百分位数,且该阈值同时适用于移动和桌面设备。
指标获取实现细节
Layout Shift 是由Layout Instability API 定义的,当视图中可见的元素在两个帧之间改变其起始位置时,该API就会报告布局偏移项。这些元素被认为是不稳定元素。
创建一个PerformanceObserver,使用Layout Instability API 来监听意外的布局变化:
let clsValue = 0;
let clsEntries = [];
let sessionValue = 0;
let sessionEntries = [];
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
// Only count layout shifts without recent user input.
if (!entry.hadRecentInput) {
const firstSessionEntry = sessionEntries[0];
const lastSessionEntry = sessionEntries[sessionEntries.length - 1];
// If the entry occurred less than 1 second after the previous entry and
// less than 5 seconds after the first entry in the session, include the
// entry in the current session. Otherwise, start a new session.
if (sessionValue
&& entry.startTime - lastSessionEntry.startTime < 1000
&& entry.startTime - firstSessionEntry.startTime < 5000) {
sessionValue += entry.value;
sessionEntries.push(entry);
} else {
sessionValue = entry.value;
sessionEntries = [entry];
}
// If the current session value is larger than the current CLS value
// update CLS and the entries contributing to it.
if (sessionValue > clsValue) {
clsValue = sessionValue;
clsEntries = sessionEntries;
// Log the updated value (and its entries) to the console.
console.log('CLS:', clsValue, clsEntries)
}
}
}}).observe({type: 'layout-shift', buffered: true});
浏览器兼容性说明
指标要求浏览器支持Layout Instability API 和 PerformanceObserver。
sdk引用polyfill来支持chrome、Firfox、Safari浏览器,理论上也可能支持chrome内核浏览器。
如何优化CLS指标
常用方法有:
- 在图片和视频元素中包含大小属性,或者用CSS长宽比框之类的东西保留所需的空间
- 不要在现有内容之上插入内容,除非是为了响应用户交互
- 多用tramsform annimations,而不是触发布局变化的annimations properties
深入了解CLS优化
参考文档
如何计算FID指标
首次输入延迟(FID)是测量加载响应度的一个以用户为中心的重要指标,因为该项指标将用户尝试与无响应页面进行交互的体验进行了量化,低FID有助于让用户确信页面是有效的。
本文指标的部分内容介绍引用自 https://web.dev/fid
什么是FID指标
Long Task 定义:在浏览器主线程执行时间超过 50ms 的 Task。
Input Delay:输入延时,记录用户和页面进行交互操作,所花费的时间。例如,从用户点击一个按钮,到浏览器正确处理这个按钮的行为,并反馈给用户所花费的时间。通常情况下,Input Delay 是因为浏览器主线程在忙于执行其他操作,无暇处理用户的交互操作。
FID(First Input Delay)测量从用户第一次与页面交互(例如当他们单击链接、点按钮或使用由JavaScript驱动的自定义控件)直到浏览器对交互作出响应,并实际能够开始处理事件处理程序所经过的时间。
FID发生在FCP和TTI之间,因为这个阶段虽然页面已经显示出部分内容,但尚不具备完全的可交互性。这个阶段用户和页面交互,往往会有较大延迟。如下图所示,浏览器接受到用户输入操作时,主线程正在忙于执行一个Long Task,只有当这个Task执行完成后,浏览器才能响应用户的输入操作。
尽管任何输入的延迟都会破坏用户体验,我们只选取FID作为通用指标是以下原因:
- FID反映用户对页面交互性和响应性的第一印象,良好的第一印象有助于用户建立对整个应用的良好印象
- 页面加载阶段,资源的处理任务最重,也最容易产生输入延迟。因此关注FID指标对提升页面的可交互性有更大收益
- FID和页面加载完成后的Input Delay 具有不同的解决方案。针对FID,我们一般建议通过Code Splitting 等方式减少页面加载阶段JS的加载、解析和执行时间。而页面加载完成的Input Delay,通常是由于开发人员代码编写不当,引起JS执行时间过长而产生的
怎样算是良好的FID分数
为了提供良好的用户体验,网站应该努力将首次输入延迟控制在100毫秒或以内。
为了确保您能够在大部分用户的访问期间达成建议目标值,一个良好的测量阈值为页面加载的第75个百分位数,且该阈值同时适用于移动和桌面设备。
web.dev 给出的FID指标的推荐时间是100ms,可以根据您站点的自身特性来适当调整。
指标计算
FID指标
FID的计算需要用户真实操作页面,可以借助Event Timing API进行测量,创建PerformanceObserver对象,监听fist-input
事件后,利用Event Timing API,通过事件的开始处理时间,减去事件的发生时间,即为FID。
因为FID的值严重依赖用户触发操作的时机,所以我们需要考虑FID值的分布曲线。
一般情况下,建议采用95分位的指标值,这能反应最差的用户交互体验对应的FID值。
如何优化FID指标
要了解如何改进某个特定网站的FID,您可以运行一次Lighthouse性能审计,并留心查看审计建议的各种具体机会。
虽然FID是一项实际指标(而灯塔是一个实验室指标工具),但改进FID的指导方向与改进总阻塞时间(TBT)这项实验室指标的指导方向相同。
如需深入了解如何改进FID,请参阅优化FID。有关其他能够改进FID的单个性能技巧的进一步指导,请参阅:
如何计算TTFB指标
Time to Fist Byte(TTFB)是衡量实验室和现场链接设置时间和Web服务器响应能力的基本指标。有助于识别Web服务器何时响应请求太慢。
在导航请求(即对HTML文档的请求)的情况下,优先于所有其他有意义的加载性能指标。
什么是TTFB
TTFB是衡量资源请求于响应的第一个字节开始到达之间时间的指标。
TTFB是以下请求阶段的总和:
- Redirect time (重定向时间)
- Service worker startup time (if applicable) (Service work 启动时间)
- DNS lookup (DNS查询)
- Connection and TLS negotiation(连接和TLS协商)
- Request,up until the point at which the first byte of the response has arriced(请求直到响应的第一个字节到达)
减少链接建立时间和后端的延迟将有助于降低TTFB。
怎么算是良好的TTFB分数
由于网络状况和应用程序后端程序实现的差异很大,所以不能在“良好”TTFB分数上放置任意的数字,因为TTFB优先于以用户为中心的指标,如First Contentful Paint (FCP)和maximum Contentful Paint (LCP),所以建议您的服务器对导航请求的响应足够快,以便75%的用户在“良好”阈值内体验FCP。
指标获取实现细节
创建一个PerformanceObserver,使用Navigation Timing API监听导航请求并上报。
具体结算时机可以参考下文的代码实现:
new PerformanceObserver((entryList) => {
const [pageNav] = entryList.getEntriesByType('navigation');
console.log(`TTFB: ${pageNav.responseStart}`);
}).observe({
type: 'navigation',
buffered: true
});
TTFB适用于所有请求,特别是跨域服务器上的资源可能会由于需要建立与这些服务器的连接而引入延迟。
要测量资源的TTFB,可以用Resource Timing API来进行监听:
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
for (const entry of entries) {
// Some resources may have a responseStart value of 0, due
// to the resource being cached, or a cross-origin resource
// being served without a Timing-Allow-Origin header set.
if (entry.responseStart > 0) {
console.log(`TTFB: ${entry.responseStart}`, entry.name);
}
}
}).observe({
type: 'resource',
buffered: true
});
使用TTFB对资源进行指标化,可能会出现0的情况,原因是资源链接已经打开或者资源从缓存中获取。
如果跨域服务器未能设置Timing-Allow-Origin标头,那么跨域请求的 TTFB 将无法在字段中测量。
浏览器兼容性说明
指标要求浏览器支持Resource Timing API 和 Navigation Timing API。
sdk引用polyfill来支持chrome、Firfox、Safari浏览器,理论上也可能支持chrome内核浏览器。
如何优化TTFB指标
偏高TTF值可能是以下原因:
- 服务器资源不足,处于高流量负载
- web服务器内存不足
- 未优化的数据库表
- 数据库服务器配置不理想
通常选择具有基础设施的合适托管提供商来最小化TTFB,以确保高运行时间和响应能力,这与cdn结合会有所帮助。
使用Server-Timing API收集有关应用程序后端进程性能的附加字段数据,这可以帮助识别可能被忽视的改进机会。
改善高TTFB时间和相关感知延迟的其他机会包括:
- 避免多个页面重定向
- 为跨源资源预连接到所需的源
- Submit your origin to the HSTS preload list to eliminate HTTP-to-HTTPS redirect latency.
- 使用 HTTP/2 or HTTP/3
- 对于那些指定偏好的用户可以减少数据使用,可以考虑对快速页面导航进行预测预取
- 在适当的情况下,服务器端生成(SSG)来标记而不是使用SSR