使用 js 和 Beacon API 实现一个简易版的前端埋点监控 npm 包

使用 js 和 Beacon API 实现一个简易版的前端埋点监控 npm 包

前端监控,埋点,数据收集,性能监控

Beacon API

https://caniuse.com/beacon

使用 js 和 Beacon API 实现一个简易版的前端埋点监控 npm 包

  1. 优点,请求发送是非阻塞的 post ,用户体验好;支持多种数据格式;

  2. 缺点,IE 不支持,使用 XHR 作为 fallback 方案

"use strict";

/**
*
* @author xgqfrms
* @license MIT
* @copyright xgqfrms
* @created 2020-01-01
* @modified
*
* @description
* @difficulty Easy Medium Hard
* @complexity O(n)
* @augments
* @example
* @link
* @solutions
*
* @best_solutions
*
*/ const log = console.log; let startTime = performance.now(); window.addEventListener(`load`, (e) => {
log(`window load`);
log(`page is fully loaded`);
}); window.addEventListener(`DOMContentLoaded`, (e) => {
log(`window DOMContentLoaded`);
// log(`DOM fully loaded and parsed`);
}); const logVisit = (url = ``) => {
// Test that we have support
if (!navigator.sendBeacon) {
// XHR fallback
return true;
} else {
// URL to send the data to, e.g.
// let url = `/api/log`;
// Data to send
let data = new FormData();
data.append(`start`, startTime);
data.append(`end`, performance.now());
data.append(`url`, document.URL);
// Let`s go!
navigator.sendBeacon(url, data);
}
}; // 将日志记录封装到一个函数中,则可以在页面卸载时调用它。
// good place for sendBeacon ??? window.addEventListener(`beforeunload`, (e) => {
log(`window beforeunload`);
// bad place for sendBeacon
logVisit(`/api/log`);
}); window.addEventListener(`unload`, (e) => {
log(`window unload`);
// bad place for sendBeacon
// logVisit(`/api/log`);
}); // navigator.sendBeacon(`https://www.xgqfrms.xyz/`, `hello `);

W3C & Beacon

W3C Candidate Recommendation 13 April 2017

https://www.w3.org/TR/beacon/

W3C Editor's Draft 30 January 2020

https://w3c.github.io/beacon/



demos





test

异常关闭浏览器窗口(强制退出 Chrome 进程),验证请求是否会发送成功?

KOA server

React client

WebSocket

load & DOMContentLoaded

https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event

https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event

readystate: interactive

DOMContentLoaded

readystate: complete

load

window.addEventListener('load', (event) => {
log.textContent = log.textContent + 'load\n';
}); document.addEventListener('readystatechange', (event) => {
log.textContent = log.textContent + `readystate: ${document.readyState}\n`;
}); document.addEventListener('DOMContentLoaded', (event) => {
log.textContent = log.textContent + `DOMContentLoaded\n`;
});

visibilitychange & pagehide

https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilitychange_event

使用 js 和 Beacon API 实现一个简易版的前端埋点监控 npm 包

"use strict";

/**
*
* @author xgqfrms
* @license MIT
* @copyright xgqfrms
* @created 2020-11-11
* @modified
*
* @description
* @difficulty Easy Medium Hard
* @complexity O(n)
* @augments
* @example
* @link
* @solutions
*
* @best_solutions
*
*/ const log = console.log; let startTime = performance.now(); window.addEventListener(`load`, (e) => {
log(`window load`);
log(`page is fully loaded`);
}); window.addEventListener(`DOMContentLoaded`, (e) => {
log(`window DOMContentLoaded`);
// log(`DOM fully loaded and parsed`);
}); const logVisit = (url = ``) => {
// Test that we have support
if (!navigator.sendBeacon) {
// XHR fallback
return true;
} else {
// URL to send the data to, e.g.
// let url = `/api/log`;
// Data to send
let data = new FormData();
data.append(`start`, startTime);
data.append(`end`, performance.now());
data.append(`url`, document.URL);
// Let`s go!
navigator.sendBeacon(url, data);
}
}; // 将日志记录封装到一个函数中,则可以在页面卸载时调用它。
window.addEventListener(`pagehide`, (e) => {
log(`window beforeunload`);
// good place for sendBeacon
logVisit(`/api/log`);
if (event.persisted) {
/* the page isn't being discarded, so it can be reused later */
}
}, false); document.addEventListener(`visibilitychange`, (e) => {
// window.addEventListener(`visibilitychange`, (e) => {
log(`document.visibilityState`, document.visibilityState);
// if (document.visibilityState === `hidden`) {
// if (document.visibilityState === `visible`) {
// backgroundMusic.play();
// } else {
// backgroundMusic.pause();
// }
// log(`window visibilitychange`);
// good place for sendBeacon
logVisit(`/api/log`);
}); window.addEventListener(`beforeunload`, (e) => {
log(`window beforeunload`);
// bad place for sendBeacon
// logVisit(`/api/log`);
}); window.addEventListener(`unload`, (e) => {
log(`window unload`);
// bad place for sendBeacon
// logVisit(`/api/log`);
}); // navigator.sendBeacon(`https://www.xgqfrms.xyz/`, `hello `);

https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event


window.addEventListener("pagehide", event => {
if (event.persisted) {
/* the page isn't being discarded, so it can be reused later */
}
}, false);

beforeunload & unload

https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event

window.addEventListener('beforeunload', (event) => {
// Cancel the event as stated by the standard.
event.preventDefault();
// Older browsers supported custom message
event.returnValue = '';
});

使用 js 和 Beacon API 实现一个简易版的前端埋点监控 npm 包

https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event

使用 js 和 Beacon API 实现一个简易版的前端埋点监控 npm 包

refs

MDN

https://developer.mozilla.org/en-US/docs/Web/API/Beacon_API

https://developer.mozilla.org/en-US/docs/Glossary/beacon

https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon


使用 js 和 Beacon API 实现一个简易版的前端埋点监控 npm 包

xgqfrms 2012-2020

www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!


上一篇:ubuntu下修改mysql默认字符编码出现的Job failed to start解决办法


下一篇:来,我们手写一个简易版的mock.js吧(模拟fetch && Ajax请求)