Web 轻量上报数据方式介绍与使用总结
一、背景
日常业务中存在一些通用场景,比如埋点,异常处理,性能监控等等,它们的数据都有以下共性特点。
数据特点:
- 不要求回调;
- 数据轻量化(大部分);
- 不需携带 cookie 凭证(跨域方便);
- 重点关心是否发送成功(在页面返回,离开,刷新等边缘情景)
二、哪种上报方式比较完美?
市面上存在多种可与服务器进行数据交互的方式,例如 xhr、fetch、script 标签、img 标签、link 标签、CSS 背景图等等,各有各自的优缺点,有没有存在比较完美的方式,既兼顾了用户体验性,又有安全性可靠性,达到业务的要求?这里我们归类一下,针对较为常用的四种上报方式:Ajax, Image, Beacon, fetch 做一下具体分析。
三、特性分析
1. Ajax
特点:
基于 XMLHttpRequest API 实现,在浏览器与 Web 服务器之间使用异步数据传输,被所有的主流浏览器支持。
优点:
-
默认异步发送,不会阻塞页面;
-
POST 方式下数据大小不限制;
-
数据存放于 body,安全性较强;
-
基本兼容现代所有浏览器;
缺点:
-
需要处理跨域限制;
-
跳转刷新关闭页面时发送数据效果较差;
-
若使用同步模式则阻塞流程影响用户体验;
2. Image
设置 img 标签的 src 属性,将采集的数据转换成字符串拼接在 url 上,并通过 GET 方式向服务端发送数据实现。
var img = new Image();
img.src = url;
特点
优点:
-
简单且天然可跨域;
-
无阻塞问题;
-
兼容所有浏览器;
缺点:
-
根据浏览器的不同,数据量有大小限制 2~8 kb;
-
GET 方式发送,安全性较差(刷量,敏感数据泄漏,浏览器插件干扰);
-
跳转刷新关闭页面时发送数据效果一般;
3. Beacon
navigator.sendBeacon 是一个比较新的,底层基于 fetch API 实现的 API,原理是通过将请求放进浏览器发送队列,用户代理在空闲时异步向服务器发送数据,不会延迟页面的卸载或者影响下个页面载入时的性能。
特点
优点:
-
异步无阻塞;
-
跳转刷新关闭页面时发送数据效果良好;
-
数据量限制一般,64k;
-
不受跨域限制;
-
POST 方式发送,安全性强;
-
浏览器兼容性中上等(除了 IE 其它都支持);
缺点:
-
只能判断出是否放入浏览器任务队列,不能判断是否发送成功;
-
不支持自定义请求头;
console.log('Send Beacon: ', navigator.sendBeacon(url, data));
// Send Beacon: true
// sendBeacon 返回值,如果成功把数据加入传输队列时,返回 true,否则为false
浏览器兼容性(除了 PC 的 IE,还行)
4. fetch
fetch API 提供了一个比 Ajax 更强大和更灵活的功能集,可返回一个 Promise 对象实现对返回结果进行检索,带有 keepalive 属性的 fetch 和 Navigator.sendBeacon() API 类似。
keepalive 属性用于页面卸载时,告诉浏览器在后台保持连接,继续发送数据。一个典型的场景就是,用户离开网页时,脚本向服务器提交一些用户行为的统计信息。这时,如果不用 keepalive 属性,数据可能无法发送,因为浏览器已经把页面卸载了。
特点
优点:
-
可配置跨域;
-
异步无阻塞,用户体验棒;
-
POST/GET, 请求头可自定义;
缺点:
-
keepalive 场景下数据量限制一般,64k;
-
浏览器兼容性较差;
fetch(url, {
method: 'POST',
body: data,
keepalive: true,
// mode: 'cors'
});
浏览器兼容性(稍微差些)
四 、实验结果(可靠性,安全性,用户体验)
1.四种发送方式在(onbeforeunload,onunload,onpopstate)等场景下的对比可见,ajax 方式和不设置 keepalive 属性下的 fetch 方式,表现效果都比 beacon,image 和 fetch(keepalive)差些。
2.数据上报优缺点对比如下
五 、结论(没有最完美的,只有更合适的)
Image:
适合发送数据量小且兼顾浏览器兼容性的场景,例如 Web 页面的页面浏览、元素点击、曝光,性能监控等行为事件;
Ajax:
适合发送数据量较大,依赖回调数据用于前端渲染和具体处理的场景,对用户体验会有一定妥协;
Beacon:
适合需要进行精确统计,页面跳转或关闭等场景做精准监控,选择 Beacon 方式能最大程度保证数据成功率;
fetch:
fetch 有逐渐替代 Ajax 的趋势,但兼容性的路仍然很长。(最艰难的 IE 时代已经被熬过去了)
所以说没有一种数据上报在各个方面都是优秀的,都有一定的优缺点,面对不同的业务需求,有时候可以通过选择不同的上报方式达到理想的要求,有时候也可以通过组合方式来达到 1+1 > 2 的效果,例如神策埋点的组合,优先判断是否兼容 beacon 方式,不兼容情况下再使用 image 方式发送。
奇妙的组合方式:
if (sendType === 'beacon' && typeof navigator.sendBeacon !== 'function') {
sendType = 'image';
}
转载自:https://juejin.cn/post/7241452578126692413