本章目录

1.目录结构

 2.安装开发依赖

3.配置rollup config js

4. src type 定义类型

5.src core 核心功能

6.工具函数 src/utils/pv

埋点就是 数据采集-数据处理-数据分析和挖掘,如用户停留时间,用户哪个按钮点的多,等

技术架构使用ts + rollup

使用ts主要是在编译过程中发现问题,减少生产代码的错误,

使用rollup 应为 rollup打包干净,而webpack非常臃肿,可读性差,所以rollup非常适合开发SDK和一些框架,webpack 适合开发一些项目

1.目录结构设计

 2.安装开发依赖

npm install rollup -D

npm install rollup-plugin-dts -D

npm install rollup-plugin-typescript2 -D

npm install typescript -D

3.配置rollup config js

import ts from 'rollup-plugin-typescript2'

import path from 'path'

import dts from 'rollup-plugin-dts';

export default [{

//入口文件

input: "./src/core/index.ts",

output: [

//打包esModule

{

file: path.resolve(__dirname, './dist/index.esm.js'),

format: "es"

},

//打包common js

{

file: path.resolve(__dirname, './dist/index.cjs.js'),

format: "cjs"

},

//打包 AMD CMD UMD

{

input: "./src/core/index.ts",

file: path.resolve(__dirname, './dist/index.js'),

format: "umd",

name: "tracker"

}

],

//配置ts

plugins: [

ts(),

]

}, {

//打包声明文件

input: "./src/core/index.ts",

output:{

file: path.resolve(__dirname, './dist/index.d.ts'),

format: "es",

},

plugins: [dts()]

}]

4. src type 定义类型

/**

* @requestUrl 接口地址

* @historyTracker history上报

* @hashTracker hash上报

* @domTracker 携带Tracker-key 点击事件上报

* @sdkVersionsdk版本

* @extra透传字段

* @jsError js 和 promise 报错异常上报

*/

export interface DefaultOptons {

uuid: string | undefined,

requestUrl: string | undefined,

historyTracker: boolean,

hashTracker: boolean,

domTracker: boolean,

sdkVersion: string | number,

extra: Record | undefined,

jsError:boolean

}

//必传参数 requestUrl

export interface Options extends Partial {

requestUrl: string,

}

//版本

export enum TrackerConfig {

version = '1.0.0'

}

//上报必传参数

export type reportTrackerData = {

[key: string]: any,

event: string,

targetKey: string

}

5.src core 核心功能

PV:页面访问量,即PageView,用户每次对网站的访问均被记录

主要监听了 history 和 hash

history API  go back  forward pushState  replaceState  

history 无法通过 popstate 监听 pushState replaceState  只能重写其函数 在utils/pv

hash 使用hashchange 监听

UV(独立访客):即Unique Visitor,访问您网站的一台电脑客户端为一个访客

用户唯一表示 可以在登录之后通过接口返回的id 进行设置值 提供了setUserId

也可以使用canvas 指纹追踪技术 Vue3 + vite + Ts + pinia + 实战 + 源码 +全栈_哔哩哔哩_bilibili

本章重点 navigator.sendBeacon

为什么要使用这个去上报

这个上报的机制 跟 XMLHttrequest 对比  navigator.sendBeacon 即使页面关闭了 也会完成请求 而XMLHTTPRequest 不一定

DOM事件监听

主要是给需要监听的元素添加一个属性 用来区分是否需要监听 target-key

js报错上报 error 事件  promise报错 unhandledrejection

import { DefaultOptons, Options, TrackerConfig, reportTrackerData } from "../types/core";

import { createHistoryEvnent } from "../utils/pv";

const MouseEventList: string[] = ['click', 'dblclick', 'contextmenu', 'mousedown', 'mouseup', 'mouseenter', 'mouseout', 'mouseover']

export default class Tracker {

public data: Options;

private version: string | undefined;

public constructor(options: Options) {

this.data = Object.assign(this.initDef(), options)

this.installInnerTrack()

}

private initDef(): DefaultOptons {

this.version = TrackerConfig.version;

window.history['pushState'] = createHistoryEvnent("pushState")

window.history['replaceState'] = createHistoryEvnent('replaceState')

return {

sdkVersion: this.version,

historyTracker: false,

hashTracker: false,

domTracker: false,

jsError: false

}

}

public setUserId(uuid: T) {

this.data.uuid = uuid;

}

public setExtra(extra: T) {

this.data.extra = extra

}

public sendTracker(data: T) {

this.reportTracker(data)

}

private captureEvents(MouseEventList: string[], targetKey: string, data?: T) {

MouseEventList.forEach(event => {

window.addEventListener(event, () => {

this.reportTracker({ event, targetKey, data })

})

})

}

private installInnerTrack() {

if (this.data.historyTracker) {

this.captureEvents(['pushState'], 'history-pv')

this.captureEvents(['replaceState'], 'history-pv')

this.captureEvents(['popstate'], 'history-pv')

}

if (this.data.hashTracker) {

this.captureEvents(['hashchange'], 'hash-pv')

}

if (this.data.domTracker) {

this.targetKeyReport()

}

if (this.data.jsError) {

this.jsError()

}

}

//dom 点击上报

private targetKeyReport() {

MouseEventList.forEach(event => {

window.addEventListener(event, (e) => {

const target = e.target as HTMLElement

const targetValue = target.getAttribute('target-key')

if (targetValue) {

this.sendTracker({

targetKey: targetValue,

event

})

}

})

})

}

private jsError() {

this.errorEvent()

this.promiseReject()

}

//捕获js报错

private errorEvent() {

window.addEventListener('error', (e) => {

this.sendTracker({

targetKey: 'message',

event: 'error',

message: e.message

})

})

}

//捕获promise 错误

private promiseReject() {

window.addEventListener('unhandledrejection', (event) => {

event.promise.catch(error => {

this.sendTracker({

targetKey: "reject",

event: "promise",

message: error

})

})

})

}

//上报

private reportTracker(data: T) {

const params = Object.assign(this.data, data, { time: new Date().getTime() })

let headers = {

type: 'application/x-www-form-urlencoded'

};

let blob = new Blob([JSON.stringify(params)], headers);

navigator.sendBeacon(this.data.requestUrl, blob)

}

}

6.工具函数 src/utils/pv

export const createHistoryEvnent = (type: T): () => any => {

const origin = history[type];

return function (this: any) {

const res = origin.apply(this, arguments)

var e = new Event(type)

window.dispatchEvent(e)

return res;

}

}

7.设置package json 

main  module 分别设置对应的js文件

files 设置打包之后的目录 我这儿是dist 具体看rollup config .js

{

"name": "zmy-tracker",

"version": "1.0.5",

"description": "",

"main": "dist/index.cjs.js",

"module": "dist/index.esm.js",

"browser":"dist/index.js",

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1",

"build": "rollup -c"

},

"keywords": ["前端","埋点","tracker"],

"author": "",

"files": ["dist"],

"license": "ISC",

"devDependencies": {

"rollup": "^2.76.0",

"rollup-plugin-dts": "^4.2.2",

"rollup-plugin-typescript2": "^0.32.1",

"typescript": "^4.7.4"

}

}

8.发布npm

tips:一定要使用npm 的源  不能使用淘宝镜像 否则 报错403

1.npm adduser

用户名 密码 邮箱 邮箱验证码

2. npm login  

输入刚才的 用户名 密码 邮箱 验证码

3.npm publish 发布

发布的时候403 有可能是名字重复注意一下

 4.npm 官网查看

zmy-tracker - npm

文章链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: