小满 前端埋点SDK 带你 从0 开发 并且发布npm

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

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


技术架构使用ts + rollup


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


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


1.目录结构设计


e40a59fbede84eda8b280c97d297c880.png


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<string, any> | undefined,
    jsError:boolean
}
//必传参数 requestUrl
export interface Options extends Partial<DefaultOptons> {
    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 <DefaultOptons>{
            sdkVersion: this.version,
            historyTracker: false,
            hashTracker: false,
            domTracker: false,
            jsError: false
        }
    }
    public setUserId<T extends DefaultOptons['uuid']>(uuid: T) {
        this.data.uuid = uuid;
    }
    public setExtra<T extends DefaultOptons['extra']>(extra: T) {
        this.data.extra = extra
    }
    public sendTracker<T extends reportTrackerData>(data: T) {
        this.reportTracker(data)
    }
    private captureEvents<T>(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<T>(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 = <T extends keyof History>(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


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


1a9ff484b4f749b5bdf49c09f734138c.png


2. npm login  


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


3.npm publish 发布


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


af6b618892f24818ae042864a3fd9ef3.png


4.npm 官网查看


zmy-tracker - npm


bba5340082b24bd7abe84939aa6713ef.png

目录
相关文章
|
6天前
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
102 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
1月前
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
174 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
2月前
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
126 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
13天前
|
前端开发 JavaScript 开发工具
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
71 5
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
17天前
|
JavaScript 编译器 开发工具
【02】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-准备工具安装-编译器DevEco Studio安装-arkts编程语言认识-编译器devco-鸿蒙SDK安装-模拟器环境调试-hyper虚拟化开启-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【02】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-准备工具安装-编译器DevEco Studio安装-arkts编程语言认识-编译器devco-鸿蒙SDK安装-模拟器环境调试-hyper虚拟化开启-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
49 2
【02】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-准备工具安装-编译器DevEco Studio安装-arkts编程语言认识-编译器devco-鸿蒙SDK安装-模拟器环境调试-hyper虚拟化开启-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
19天前
|
安全 前端开发 开发工具
【01】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-优雅草卓伊凡拟开发一个一站式家政服务平台-前期筹备-暂定取名斑马家政软件系统-本项目前端开源-服务端采用优雅草蜻蜓Z系统-搭配ruoyi框架admin后台-全过程实战项目分享-从零开发到上线
【01】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-优雅草卓伊凡拟开发一个一站式家政服务平台-前期筹备-暂定取名斑马家政软件系统-本项目前端开源-服务端采用优雅草蜻蜓Z系统-搭配ruoyi框架admin后台-全过程实战项目分享-从零开发到上线
55 5
【01】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-优雅草卓伊凡拟开发一个一站式家政服务平台-前期筹备-暂定取名斑马家政软件系统-本项目前端开源-服务端采用优雅草蜻蜓Z系统-搭配ruoyi框架admin后台-全过程实战项目分享-从零开发到上线
|
1月前
|
JSON 前端开发 测试技术
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
96 10
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
|
1月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
176 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
26天前
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
61 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
|
2月前
|
API 开发工具 Android开发
【01】完整开发即构美颜sdk的uni官方uts插件—让所有开发者可以直接使用即构美颜sdk的能力-优雅草卓伊凡
【01】完整开发即构美颜sdk的uni官方uts插件—让所有开发者可以直接使用即构美颜sdk的能力-优雅草卓伊凡
80 23
【01】完整开发即构美颜sdk的uni官方uts插件—让所有开发者可以直接使用即构美颜sdk的能力-优雅草卓伊凡

热门文章

最新文章

  • 1
    【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
  • 2
    CompreFace:Star6.1k,Github上火爆的轻量化且强大的人脸识别库,api,sdk都支持
  • 3
    【02】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-准备工具安装-编译器DevEco Studio安装-arkts编程语言认识-编译器devco-鸿蒙SDK安装-模拟器环境调试-hyper虚拟化开启-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
  • 4
    【Azure Developer】编写Python SDK代码实现从China Azure中VM Disk中创建磁盘快照Snapshot
  • 5
    【Azure Storage Account】利用App Service作为反向代理, 并使用.NET Storage Account SDK实现上传/下载操作
  • 6
    从前端视角聊聊通义灵码使用经验,如何更好地提升研发效率
  • 7
    VSCode AI提效工具,通义灵码前端开发体验
  • 8
    前端跨域问题解决Access to XMLHttpRequest at xxx from has been blocked by CORS policy
  • 9
    【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
  • 10
    大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
  • 推荐镜像

    更多