码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 性能监控计算——封装带性能计算并上报的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

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

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

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

    💖 最后,感谢你的阅读!

  • 相关阅读:
    1.4 系统环境变量
    【HHO-KELM预测】基于哈里斯鹰算法优化核极限学习机回归预测研究(Matlab代码实现)
    【现代 CSS】标准滚动条控制规范 scrollbar-color 和 scrollbar-width
    x^n的导数
    QML:拖动曲线坐标点修改曲线
    java 两种写txt文件的方式
    RK3588开发笔记(二):基于方案商提供sdk搭建引入mpp和sdk的宿主机交叉编译Qt5.12.10环境
    C语言 牛客网习题 10.20 day2
    关于软件物料清单(SBOM),你所需要了解的一切
    你知道this.$options吗?(Vue)
  • 原文地址:https://blog.csdn.net/qq_38870145/article/details/139401047
  • 最新文章
  • 沪漂五周年了:我越来越迷茫了
    Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
    MySQL-Seconds_behind_master的精度误差
    [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
    AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
    Agent OS :五种驯服不确定性的范式
    PortSwigger SQL注入LAB11
    数据库即时编译JIT
    [Begin]AI Learn Data Day 0
    深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号