实现埋点功能的意义主要体现在以下几个方面:
总之,实现埋点功能可以帮助企业更好地了解用户需求和行为习惯,优化产品和服务,改进决策,优化运营并预测趋势,具有重要的意义和作用。
常见的埋点包括:pv【PageView】上报(包括history上报、hash上报)、uv【UserView】上报、dom事件上报、js报错上报(包括常规错误上报、Promise报错上报)
下面我们通过使用nodejs、TypeScript、rollup等技术栈实现一个简易的埋点上报的sdk,并发布npm。
通过这篇文章你可以学习到:前端埋点&监控、区分js模块化、打包工具rollup、API之History、JS二进制、sendBeacon发送post请求等知识。
因为要在nodejs环境下并使用rollup打包输出支持不同规范的模块,因此了解JS模块化相关知识是必要的。
主流模块化规范有:
这里建议看一下这边博客:前端模块化详解(完整版),里面详细讲解了主流模块
下面我们对主流模块做个总结,如下:
序号 |
模块化规范 |
备注 |
1 |
CommonJS |
CommonJS规范主要用于服务端编程,加载模块是同步的,这并不适合在浏览器环境,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD和CMD解决方案 |
2 |
AMD |
AMD规范在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过,AMD规范开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅。 |
3 |
CMD |
CMD规范整合了CommonJS和AMD规范的特点, CMD规范与AMD规范很相似,都用于浏览器编程,依赖就近,延迟执行,可以很容易在Node.js中运行。不过,依赖SPM打包,模块的加载逻辑偏重 |
4 |
UMD |
UMD是AMD和CommonJS两者的结合,这个模式中加入了当前存在哪种规范的判断,所以能够“通用”,它兼容了AMD和CommonJS,同时还支持老式的“全局”变量规范 |
5 |
ESM |
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。 |
要发布npm包,打包库是必然的,而rollup比webpack更适合打包库,因此学习rollup也是必要的。
建议看一下这篇博客:安装 Rollup 以及 Rollup 和 Webpack 的区别
这里总结一下rollup和webpack的区别:
实现Page View埋点往往需要使用HistoryAPI,因为它可以帮助我们更好地控制页面的状态和导航。
在SPA中,页面的状态通常由内部状态管理,而不是通过URL来表现。因此,传统的PV埋点方法(例如通过document.referrer)可能无法正确计算PV。
使用History API可以让我们更精细地控制页面的导航和状态。我们可以使用history.pushState()方法将新的状态添加到历史记录中,并更新URL,但不会触发页面刷新。这样,我们可以在用户与页面交互时跟踪其导航路径,并计算PV。
另外,当用户点击浏览器的后退按钮时,我们可以使用popstate事件来获取上一个历史记录状态,并根据需要进行处理。这可以帮助我们处理用户在SPA中的导航,并提供更准确的PV数据。
History 接口允许操作浏览器的曾经在标签页或者框架里访问的会话历史记录,它的实例方法back()、forward()、go()大家应该都比较熟悉就不一一介绍了,这里主要介绍一下pushState()和replaceState()以及popstate事件,注意:popstate事件并么有使用驼峰命名方式。
在HTML文档中,history.pushState()方法向浏览器的会话历史栈增加了一个条目。该方法是异步的。为 popstate 事件增加监听器,以确定导航何时完成。state 参数将在其中可用。
语法:history.pushState(state, title, url)
其中,state 对象是一个 JavaScript 对象,其与通过 pushState() 创建的新历史条目相关联。每当用户导航到新的 state,都会触发 popstate 事件,并且该事件的 state 属性包含历史条目 state 对象的副本。
title标题,由于历史原因是个必填项。url可以是相对路径也可以是绝对路径,浏览器会跳转到对应页面。
对比window.loacation
从某种程度来说,调用 pushState() 类似于 window.location = "#foo"(window.location.hash将变成#foo,hash一般情况下为url后#及其后面一部分组成,这一部分为网页的位置,也称为为锚点),它们都会在当前的文档中创建和激活一个新的历史条目。但是 pushState() 有以下优势:
更详细内容可以看MDN——pushState()方法
replaceState()方法使用state objects, title,和 URL 作为参数,修改当前历史记录实体,如果你想更新当前的 state 对象或者当前历史实体的 URL 来响应用户的的动作的话这个方法将会非常有用。
语法:history.replaceState(stateObj, title[, url])
更详细内容可以看MDN——replaceState()方法
每当激活同一文档中不同的历史记录条目时,popstate 事件就会在对应的 window 对象上触发。如果当前处于激活状态的历史记录条目是由 history.pushState() 方法创建的或者是由 history.replaceState() 方法修改的,则 popstate 事件的 state 属性包含了这个历史记录条目的 state 对象的一个拷贝。
调用 history.pushState() 或者 history.replaceState() 不会触发 popstate 事件。popstate 事件只会在浏览器某些行为下触发,比如点击后退按钮(或者在 JavaScript