嗦嗦postMessage和webSocket

news2024/11/23 15:17:28

前端监控

本文将从前端监控要做的3件事讲起,以及看看github上的web-tracing插件是怎么做的,尽可能展开里面关于用户体验的知识点。主要有以下几点:

  • 行为监控
  • 错误收集
  • 性能监控### 行为监控

行为监控就是页面上加装摄像头,把我们的页面看作是游乐园,把游客访问页面看作是进游乐园游玩。那么只要在游乐园的门口,与各个主题园区加装上一个闸门,就能清楚知道游乐园里面有多少游客,那个主题最受欢迎。然后在游乐园的商店门口加装摄像头,可以监测到特定的店铺吸引哪些用户群体。换过来我们浏览器也相同,我们在进入页面的时候,触发路由事件就是游乐园的门,在页面上触发的鼠标事件就像是摄像头,页面的行为监控大致就是这些。

为什么要做用户的行为情况监控?其实也就是问:采集了用户的行为信息后我们能做什么,答案其实很简单:

  • PV、UV量,日同比、周同比等。能清晰的明白流量变化
  • 用户热点页面、高访问量TOP10
  • 设备、浏览器语言、浏览器、活跃时间段等的用户特征
  • 用户的行为追踪:某个用户,进入了网站后的一系列操作或者跳转行为;
  • 用户自定义埋点上报用户行为:想做一些自定义事件的监听,比如播放某个视频的行为动作
  • 多语种站点,每个语种的用户量
收集页面级的数据

那怎么收集页面的 PVUV 呢,这里大概给一个思路,也是我给公司用的自研监控系统中的思路。

一般的路由跳转行为,都是针对于 SPA单页应用的,因为对于非单页应用来说,url跳转都以页面刷新的形式;

接着往下阅读之前,我们先来了解一下,html5History API ,它所支持的 API 有以下五个

  • history.back()
  • history.go()
  • history.forward()
  • history.pushState()
  • history.replaceState()

同时在 History API 中还有一个 事件 ,该事件为 popstate;它有着以下特点;

  • History.back()History.forward()History.go()在被调用时,会触发 popstate事件
  • 但是History.pushState()History.replaceState()不会触发 popstate事件

所以我们需要对 replaceStatepushState,去创建新的全局Event事件。然后 window.addEventListener 监听我们加的 Event 即可

可以通过 window.history.pushStatepopstatehashchange 触发页面级的统计,可以参考以下代码:

window.history.pushState = (data, title, url) => {// ... 这里收集页面级的数据
};
window.history.replaceState = (data, title, url) => {// ... 这里收集页面级的数据
};

// hash变化也会触发popstate事件,而且会先触发popstate事件
// 可以使用popstate来代替hashchange,如果支持History H5 Api
// https://developer.mozilla.org/zh-CN/docs/Web/API/Window/popstate_event
window.addEventListener('popstate', () => {if (window.location.hash !== '') {// ... 这里收集页面级的数据}
});
window.addEventListener('hashchange', () => {// ... 这里收集页面级的数据
}); 

对了,还可以从数据请求入手,用户请求了什么接口都可以监控、收集,但是这个也是有一定的入侵性,因为可能要重写 XMLHttpRequest 或者 Fetch 。 下面也是贴一下主要代码:

// XMLHttpRequest 劫持 open方法
XMLHttpRequest.prototype.open = function (method, url, async) {_config.requestMethod = method;_config.src = url;return open.call(this, method, url, async);
};

// 劫持 send方法
XMLHttpRequest.prototype.send = function(body) {// body 就是post方法携带的参数// readyState发生改变时触发,也就是请求状态改变时// readyState 会依次变为 2,3,4 也就是会触发三次这里this.addEventListener('readystatechange', () => {if (readyState === 4) { // 请求已完成,且响应已就绪if (status === 200 || status === 304) {// ... 这里收集用户请求成功的数据} else if (errorServer) {// ... 这里收集用户请求失败的数据}}});return send.call(this, body);
}; 
// fetch请求拦截
const nativeFetch = window.fetch;
if (nativeFetch) {window.fetch = function traceFetch(target, options = {}) {const fetchStart = Date.now();const { method = 'GET' } = options;const result = nativeFetch(target, options);result.then((res) => {const { url, status, statusText } = res;if (status === 200 || status === 304) {// ... 这里收集用户请求成功的数据} else if (errorServer) {// ... 这里收集用户请求失败的数据}}, (e) => {// 无法发起请求,连接失败});return result;};
} 

收集用户设备交互行为

页面级的收集解决了,接下来看看怎么收集用户的鼠标、键盘事件。有两种思路:

  • 第一种:无代码入侵的,全量收集的* 即在全局使用click、mouseenter、dblclick等事件,用户只要在页面内有这些动作,就会被收集
  • 第二种:需要在代码里面将需要收集交互的dom标记起来,用户与它交互时收集* 在特定的dom绑定事件,也可以在document绑定,用事件委托的方法触发收集逻辑

这里贴一下代码:

// 第一种思路收集方式
document.addEventListener('click', (e) => { // 点击事件;// ... 这里收集用户交互的数据
}, true);
document.addEventListener('mouseenter', (e) => { // 点击事件;// ... 这里收集用户交互的数据
}, true);
document.addEventListener('dblclick', (e) => { // 点击事件;// ... 这里收集用户交互的数据
}, true);

// 第二种思路收集方式
document.addEventListener('click', function(e) {// 检查事件源e.targe是否为Liif (e.target && e.target.nodeName.toUpperCase == "DIV") {// ...}
} 
```### 前端错误收集

`前端错误收集`包括但不限于:怎么捕获前端错误,发生错误的时候应该上报什么信息,还有展示端的设计。

下面是一些捕获错误的途经:

* `window.onerror`  window.onerror函数会在页面发生js错误时被调用* `addEventListener('error', callback, true)`  在捕获阶段捕捉资源加载错误信息```
window.addEventListener('error', (e) => {// ... 这里收集页面报错数据// 捕获阶段可以获取资源加载错误,script.onError link.onError img.onError,无法知道具体状态
}, true); 
  • addeventListener('unhandledrejection',callback)  捕获 Promise 错误
window.addEventListener('unhandledrejection', (e) => {// ... 这里收集Promise报错数据
}); 
  • vue3环境下app.config.errorHandler  捕获vue环境下的错误### 性能监控

用户打开我们的页面,需要等待多长时间才有画面出来,什么时候才能和页面交互,这个时间越短,用户的体验越好,所以一般我们会用到一些性能指标。

下面是一些常见的性能指标

FP 白屏(First Paint Time )  从页面开始加载到浏览器中检测到渲染(任何渲染)时被触发(例如背景改变,样式应用等)

FCP 首屏(first contentful paint )  从页面开始加载到页面内容的任何部分呈现在屏幕上的时间。关注的焦点是内容,这个度量可以知道用户什么时候收到有用的信息(文本,图像等)

FMP 首次有效绘制(First Meaningful Paint )  表示页面的“主要内容”,开始出现在屏幕上的时间点,这项指标因页面逻辑而异,因此上不存在任何规范。 (只是记录了加载体验的最开始。如果页面显示的是启动图片或者 loading 动画,这个时刻对用用户而言没有意义)

LCP(Largest Contentful Paint )  LCP 指标代表的是视窗最大可见图片或者文本块的渲染时间。 (可以帮助我们捕获更多的首次渲染之后的加载性能,但这项指标过于复杂,而且很难解释,也经常出错,没办法确定主要内容什么时候加载完。)

长任务(Long Task)  当一个任务执行时间超过 50ms 时消耗到的任务 (50ms 阈值是从 RAIL 模型总结出来的结论,这个是 google 研究用户感知得出的结论,类似用户的感知/耐心的阈值,超过这个阈值的任务,用户会感知到页面的卡顿)

TTI (Time To Internative)  从页面开始到它的主要子资源加载到能够快速地响应用户输入的时间。(没有耗时长任务)

首次输入延时 FID (first Input Delay)  从用户第一次与页面交互到浏览器实际能够开始处理事件的时间。(点击,输入,按键)

CLS(Cumulative Layout Shift)  是所有布局偏移分数的汇总,凡是在页面完整生命周期内预料之外的布局偏移都包括。布局偏移发生在任意时间,当一个可见元素改变了它的位置,从一个渲染帧到下一个

使用Performance API获取上面的指标

Performance 是一个浏览器全局对象,提供了一组 API 用于编程式地获取程序在某些节点的性能数据。它包含一组高精度时间定义,以及配套的相关方法。下面是掘金写作页面的window.performance

其中memory代表内存,navigation代表来源,最重要的是timing,从timing可以得到的信息有很多,包括HTTPS 连接开始的时间HTTP 响应全部接收完成的时间(获取到最后一个字节)DNS 域名查询开始与结束的时间开始解析渲染 DOM 树的时间与渲染结束的时间网页内资源加载开始和结束的时间,得到这些关键的时间点后,通过一些简单的计算,就能得出前端性能指标了

  • FP:responseStart - navigationStart
  • 重定向耗时:redirectEnd - redirectStart
  • DNS 查询耗时:domainLookupEnd - domainLookupStart
  • TCP 链接耗时:connectEnd - connectStart
  • HTTP 请求耗时:responseEnd - responseStart
  • 解析 dom 树耗时:domComplete - domInteractive
  • DOM ready 时间:domContentLoadedEventEnd - navigationStart
  • onload:loadEventEnd - navigationStart

其中LCP(Largest Contentful Paint )指标是比较难定义的,可能每个网站的界定都不太一样,因为每个网站的侧重点都不一样,就像淘宝和B站。

FMP智能获取算法,由于首次有意义绘制比较主观,开发者一般需要自行指定究竟哪些属于有意义的渲染元素,因此可以通过 FMP 的智能获取算法来自定义 FMP 时间。该算法的实现过程大概如下:

  • 先定义元素* 体积占比大的* 屏幕内可见比大的* 属于资源加载元素的,例如:img、video、canvse等
  • 根据元素对页面视觉的贡献,进行元素的权重划分,例如:img->2,video->3,canvas->3
  • 对成个页面进行深度优先遍历搜索,然后对每个元素进行权重计算,具体通过element.getBoundingClientRect获取元素的位置和大小
  • 最终将页面的所有元素权重总和的平均值,然后过滤出在平均分之上的元素集合,就得到了一个 FMP 时间。

Performance强大,但有缺点。就是在单页面应用中,改变 URL 时,使用 Performance 所获取的数据是不会更新的,这时候需要开发者重新设计统计方案。

这里更贴张 W3C第二版的 Navigation Timing 的处理模型(上一篇文章用的图相对比较老一点,新的图特意划分出 Resource Timing 时间,职责划分更加清晰)

最后

整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/53786.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于PHP+MySQL大学宿舍管理系统的设计与实现

高等学校的住宿宿舍是住宿的第二个家,是住宿进行学习与工作的重要场地。其管理水平的高低将直接影响着住宿人才培养的质量和住宿素质教育的成效。为住宿提供一个良好的管理体系,对学校和住宿而言至关重要,因此高校公寓的建设与发展,直接影响着学校后勤社会化改革的发展进程,也直…

有趣且重要的JS知识合集(17)矩形框交互算法

之前我讲过如何用js绘制矩形框,下面链接快速通道~ 【JS】原生js实现矩形框的绘制/拖动/缩放 那么如何判断多个矩形框是否相交?嵌套还是其他的呢? 那下面我来分别写写关于矩形框常用的几个算法吧 1、数据格式知悉 const { startX, startY…

网页整体如何实现网页变灰效果

网页整体如何变灰?为了纪念一些影响力很大的伟人逝世或者重要的纪念日的时候需要让网页全部变灰来表示我们对逝者的悼念。 其实这个功能很简单&#xff0c;方法也有很多&#xff0c;只需要在HTML 的head标签里加入如下代码即可! <style type"text/css">html …

Vulnhub_CTF-4

目录 一 渗透测试 &#xff08;一&#xff09;信息收集 1 端口扫描 2 目录枚举 &#xff08;二&#xff09;漏洞测试 1 SQL注入 2 ssh爆破 &#xff08;三&#xff09;提权 1 sudo 提权 二 知识点 &#xff08;一&#xff09;SQL延时注入 &#xff08;二…

Vue3聊天气泡简单实现思路

Vue3聊天气泡简单实现 实现聊天气泡主要有两个注意点&#xff1a; ①是根据字体数量自适应框的长度 ②字体到框有边距&#xff0c;也就是为了美观 这篇博客主要讲实现的思路&#xff0c;不讲聊天气泡的三角突出点&#xff0c;如下所示&#xff1a; 三角突出点通过简单的bord…

微服务框架 SpringCloud微服务架构 9 初识 Docker 9.1 什么是Docker

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构9 初识 Docker9.1 什么是Docker9.1.1 项目部署的问题9.1.2 Docker9.1.3 总…

StarkNet新手指南

Rollup代表了以太坊未来扩展计划的基础。 StarkNet是一个无需许可的第2层&#xff08;L2&#xff09;扩展网络&#xff0c;是“四大”早期主流rollup之一。本篇Bankless文章将向你展示&#xff0c;对于一个新手来说&#xff0c;如何畅游StarkNet生态系统&#xff01; StarkNe…

【JUC】循环屏障CyclicBarrier详解

前言 jdk中提供了许多的并发工具类&#xff0c;大家可能比较熟悉的有CountDownLatch&#xff0c;主要用来阻塞一个线程运行&#xff0c;直到其他线程运行完毕。而jdk还有一个功能类似并发工具类CyclicBarrier&#xff0c;你知道它的作用吗&#xff1f;和CountDownLatch有什么区…

QA特辑|重点重点!模型开发与部署的标准答案!

11月24日&#xff0c;顶象业务安全大讲堂系列课程之《智能模型平台》正式开讲&#xff0c;顶象人工智能总监无常从从模型平台的现状与需求出发&#xff0c;带大家了解了模型平台的开发环境与部署环境&#xff0c;并且就顶象的Xintell 模型平台 为大家做了演示。 直播也吸引了不…

【LeetCode每日一题】——38.外观数列

文章目录一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【解题思路】七【题目提示】八【时间频度】九【代码实现】十【提交结果】一【题目类别】 字符串 二【题目难度】 中等 三【题目编号】 38.外观数列 四【题目描述】 给定一个正整数 n …

mybatispuls 批处理 rewriteBatchedStatements=true

mybatis-plus原生的批处理 this.saveBatch(list); 实际是一条条处理&#xff0c;特慢&#xff0c;造几万行数据得几分钟以上。 如果加上配置&#xff0c;就十几秒搞定五万行数据入库 &rewriteBatchedStatementstrue

建议收藏——等级保护备案整体流程

等级保护的流程大致为定级—备案—初测—整改—复测—监督检查&#xff0c;备案需先定级。整体备案流程是向属地公安机关提交备案资料&#xff0c;需要先线上提交备案材料。线上审核通过后&#xff0c;再线下提交备案材料。具体如下&#xff1a; 1&#xff0c;先线上提交资料审…

WPF 3D MeshGeometry3D类的Positions和TriangleIndices属性研究

MeshGeometry3D 类&#xff0c;用于生成三维形状的三角形基元&#xff1b; 类的参考在此&#xff1b; https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.media.media3d.meshgeometry3d?viewwindowsdesktop-7.0 写在xaml语法里面是<MeshGeometry3D Positions.…

【Android App】低功耗蓝牙中扫描BLE设备的讲解及实战(附源码和演示 超详细)

需要源码请点赞关注收藏后评论区留言私信~~~ 一、扫描BLE设备 传统蓝牙虽然历史悠久&#xff0c;但它的缺陷也很明显&#xff0c;包括但不限于下列几点&#xff1a; &#xff08;1&#xff09;需要两部设备配对之后才能继续连接&#xff0c;而且连接速度也慢&#xff1b; &a…

数组与字符串总结

一、数组 基本概念 特点&#xff1a;顺序存储&#xff0c;每个元素大小&#xff0c;类型相同&#xff0c;元素有限 高维数组可以转化为一维数组 高维数组存放次序&#xff1a;按行优先或者按列优先 按行优先的寻址公式&#xff1a; 二维数组a[m] [n]: Loc(a[i] [j]) Loc…

Ajax axios JSON Fastjson

1、概述 AJAX (Asynchronous JavaScript And XML) &#xff1a;异步的JavaScript和XML AJAX工作流程如下: 1.1、作用 AJAX作用有以下两方面&#xff1a; 1&#xff09;与服务器进行数据交换&#xff1a;通过AJAX可以给服务器发送请求&#xff0c;服务器将数据直接响应回浏览…

算法训练Day36 贪心算法系列 - 重叠区间问题 | LeetCode435. 无重叠区间;763. 划字母区间;56.合并区间

前言&#xff1a; 算法训练系列是做《代码随想录》一刷&#xff0c;个人的学习笔记和详细的解题思路&#xff0c;总共会有60篇博客来记录&#xff0c;计划用60天的时间刷完。 内容包括了面试常见的10类题目&#xff0c;分别是&#xff1a;数组&#xff0c;链表&#xff0c;哈…

【Linux】快捷键

Ctrl C&#xff1a;终止当前命令

星环科技数据中台解决方案,助力某政府机构建设新型智慧城市

客户背景 城市&#xff0c;是人们工作生活的栖息地&#xff0c;也是展示发展成果的全景图。某政府机构不仅注重城市“中枢大脑”的建设&#xff0c;而且兼顾“神经末梢”的需求&#xff0c;既有技术进步的“面子”&#xff0c;更有民生保障的“里子”。站在新的起点上&#xff…

Linux计划任务管理

一&#xff0c;计划任务管理&#xff1a; 任务管理很宽泛&#xff0c;这里是指的计划任务管理&#xff0c;在指定的时间执行。 1&#xff0c;at命令 &#xff1a; 由atd守护进程来执行&#xff0c;atd进程会定期检查系统上的 /var/spool/at 目录&#xff0c;获取at命令写入的任…