• 性能监控计算——封装带性能计算并上报的npm包(第三章)


    yma16-logo

    ⭐前言

    大家好,我是yma16,本文分享 性能监控计算——封装带性能计算并上报的npm包(第三章)。

    背景

    为了实现前端性能耗时的数据监控,前端对外发布js的sdk,sdk的功能主要是性能耗时计算和数据上报。同时使用vue3和node开发一个数据监控的后台管理系统,主要功能是展示数据,提供一个api_key和token对外暴露的api接口去添加数据监控数据。

    功能:封装性能耗时并上报的npm包。

    rollup打包js

    Rollup 是一个用于 JavaScript 的模块打包工具,它将小的代码片段编译成更大、更复杂的代码,例如库或应用程序。它使用 JavaScript 的 ES6 版本中包含的新标准化代码模块格式,而不是以前的 CommonJS 和 AMD 等特殊解决方案。ES 模块允许你自由无缝地组合你最喜欢的库中最有用的个别函数。

    node系列往期文章
    node_windows环境变量配置
    node_npm发布包
    linux_配置node
    node_nvm安装配置
    node笔记_http服务搭建(渲染html、json)
    node笔记_读文件
    node笔记_写文件
    node笔记_连接mysql实现crud
    node笔记_formidable实现前后端联调的文件上传
    node笔记_koa框架介绍
    node_koa路由
    node_生成目录
    node_读写excel
    node笔记_读取目录的文件
    node笔记——调用免费qq的smtp发送html格式邮箱
    node实战——搭建带swagger接口文档的后端koa项目(node后端就业储备知识)
    node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)
    node实战——koa给邮件发送验证码并缓存到redis服务(node后端储备知识)

    koa系列项目文章
    前端vite+vue3结合后端node+koa——实现代码模板展示平台(支持模糊搜索+分页查询)
    node+vue3+mysql前后分离开发范式——实现对数据库表的增删改查
    node+vue3+mysql前后分离开发范式——实现视频文件上传并渲染

    koa-vue性能监控到封装sdk系列文章
    性能监控系统搭建——node_koa实现性能监控数据上报(第一章)
    性能监控系统搭建——vue3实现性能监控数据展示(第二章)

    ⭐ rollup + ts 初始化

    💖npm init

    package

    {
      "name": "web-performance",
      "version": "1.0.0",
      "description": "",
      "type": "module",
      "main": "./src/main.ts",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build": "rollup --config"
      },
      "keywords": [
        "performance"
      ],
      "author": "yma16",
      "license": "ISC",
      "dependencies": {
        "axios": "^1.7.2"
      },
      "devDependencies": {
        "@rollup/plugin-commonjs": "^25.0.8",
        "@rollup/plugin-json": "^6.1.0",
        "@rollup/plugin-node-resolve": "^15.2.3",
        "@rollup/plugin-terser": "^0.4.4",
        "@rollup/plugin-typescript": "^11.1.6",
        "rollup-plugin-babel": "^4.4.0",
        "rollup-plugin-commonjs": "^10.1.0",
        "rollup-plugin-terser": "^7.0.2",
        "rollup-plugin-typescript2": "^0.36.0",
        "typescript": "^5.4.5"
      }
    }
    
    

    💖src目录编写 main.ts 逻辑上报fmp

    main.ts

    import { setToken, report } from "./api/index";
    type PerfEnum = "fmp_count" | "dns_count" | "dcl_count" | "tcp_count";
    type PerfType = {
      fmp_count: number;
      dcl_count: number;
      dns_count: number;
      tcp_count: number;
    };
    
    class WebPerformance {
      // performance
      private performanceConfig: PerfType = {
        fmp_count: 0,
        dcl_count: 0,
        dns_count: 0,
        tcp_count: 0,
      };
    
      // api header的token
      private token: string = "";
    
      // 完成计算
      private isFinishCalPerf = false;
    
      /**
       * 构造函数
       * @param {*} options
       */
      constructor(options: { token: string }) {
        if (options.token) {
          this.setTokenAction(options.token);
        }
        this.clacPerf();
      }
    
      /**
       * 配置请求的token
       * @param {*} token
       */
      public setTokenAction(token: string) {
        this.token = token;
        setToken(this.token);
        if (this.isFinishCalPerf ) {
          this.reportAction({
            ...this.getPerformance(),
            name: "appRelaunch",
            type: "appRelaunch",
            path: location.href,
          });
        }
      }
    
      /**
       * 上报
       * @param {*} params
       */
      public reportAction(params: any) {
        if (!this.token) {
          return console.warn("no token");
        }
        report({ params });
      }
    
      /**
       * 计算耗时
       */
      private clacPerf() {
        const observer = new PerformanceObserver((list) => {
          list.getEntries().forEach((entry: any) => {
            // 使用performance计算默认耗时
            const domContentLoadedTime =
              entry.domContentLoadedEventEnd - entry.domContentLoadedEventStart;
            const dnsLoadedTime = entry.domainLookupEnd - entry.doaminLookupStart;
            const tcpLoadedTime = entry.connectEnd - entry.connectStart;
            const fmpLoadedTime = entry.domContentLoadedEventEnd - entry.startTime;
    
            this.setPerformance("fmp_count", fmpLoadedTime);
            this.setPerformance("dns_count", dnsLoadedTime);
            this.setPerformance("tcp_count", tcpLoadedTime);
            this.setPerformance("dcl_count", domContentLoadedTime);
            this.isFinishCalPerf = true;
            // 延时上报
            setTimeout(() => {
              this.reportAction({
                ...this.getPerformance(),
                name: "appRelaunch",
                type: "appRelaunch",
                path: location.href,
              });
            });
          });
        });
    
        observer.observe({ type: "navigation", buffered: true });
      }
    
      /**
       * 获取performance
       * @returns
       */
      getPerformance() {
        return this.performanceConfig;
      }
    
      /**
       * 配置performance
       * @param {*} key
       * @param {*} value
       */
      private setPerformance(key: PerfEnum, value: number) {
        this.performanceConfig[key] = value;
      }
    }
    
    export { WebPerformance };
    
    

    api 调用axios

    import axios from 'axios';
    // 添加请求拦截器
    axios.interceptors.request.use(function(config) {
        // 在发送请求之前做些什么
        return config;
    }, function(error) {
        // 对请求错误做些什么
        return Promise.reject(error);
    });
    
    // 添加响应拦截器
    axios.interceptors.response.use(function(response) {
        // 2xx 范围内的状态码都会触发该函数。
        // 对响应数据做点什么
        return response;
    }, function(error) {
        // 超出 2xx 范围的状态码都会触发该函数。
        // 对响应错误做点什么
        return Promise.reject(error);
    });
    
    // 创建实例时配置默认值
    const instance = axios.create({
        baseURL: ''
    });
    
    export default instance
    

    接口上报report

    import request from "./request";
    
    export const setToken = (token: string) => {
      request.defaults.headers.common["Authorization"] = `${token}`;
    };
    
    export const report: any = (params: any) => {
      return request.post("/cloudApi/perf/list", params);
    };
    
    

    💖tsconfig配置

    tsconfig.json配置

    {
      "compilerOptions": {
        "moduleResolution": "node",
        "target": "es5",
        "module":"es2015",
        "lib": ["es2015", "es2016", "es2017", "dom"],
        "strict": true,
        "sourceMap": true,
        "declaration": true,
        "allowSyntheticDefaultImports": true,
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "declarationDir": "dist/types",
        "resolveJsonModule": true,
        "outDir": "dist/es",
        "typeRoots": [
          "node_modules/@types",
        ]
      },
     "include": ["src",], // 包含要编译的文件  
    }
    
    

    💖rollup 配置

    rollup.config.js

    // rollup.config.js  
    import typescript from '@rollup/plugin-typescript';
    import resolve from '@rollup/plugin-node-resolve';
    import commonjs from '@rollup/plugin-commonjs';
    import json from '@rollup/plugin-json';
    import babel from 'rollup-plugin-babel';
    // import terser from '@rollup/plugin-terser';
    export default {
        input: 'src/main.ts',
        output: [{
            file: 'dist/index.js',
            sourcemap: false // 生成 source map  
                // format: 'iife', // 输出的格式  
        }],
        plugins: [
            typescript(),
            resolve(),
            commonjs(),
            babel(),
            json(),
        ],
        // axios太大 排除打包
        external: ['axios']
    };
    

    ⭐打包结果

    打包json格式化index.js,其中类型已经自动转移到types目录下

    image.png

    💖npm使用

    import {WebPerformance} from 'web-performance-tool';
    new WebPerformance({token:'token字符串自动上报'});
    

    💖查看上报的数据

    image.png

    ⭐结束

    💖数据分布展示效果

    在这里插入图片描述

    本文分享到这结束,如有错误或者不足之处欢迎指出!

    image.png

    👍 点赞,是我创作的动力!

    ⭐️ 收藏,是我努力的方向!

    ✏️ 评论,是我进步的财富!

    💖 最后,感谢你的阅读!

  • 相关阅读:
    奶爸级教学---webpack详细教学
    面试突击:什么是粘包和半包?怎么解决?
    nacos配置管理
    [附源码]SSM计算机毕业设计志愿者管理系统论文2022JAVA
    02_RabbitMQ入门及安装
    深度学习的数学基础
    Java之I/O
    Go的error接口
    CGAN理论讲解及代码实现
    并行与分布式计算 第一章 基本概念
  • 原文地址:https://blog.csdn.net/qq_38870145/article/details/139401047