├── LICENSE ├── README.en.md ├── README.md ├── backend ├── .autod.conf.js ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .travis.yml ├── README.md ├── app │ ├── controller │ │ ├── home.js │ │ └── mointor.js │ ├── middleware │ │ └── error_handler.js │ ├── router.js │ └── utils │ │ ├── sendMail.js │ │ └── stackparser.js ├── appveyor.yml ├── config │ ├── config.default.js │ └── plugin.js ├── jsconfig.json └── package.json └── vue-app ├── .env.development ├── .env.production ├── .gitignore ├── .vscode └── extensions.json ├── README.md ├── index.html ├── package.json ├── public └── favicon.ico ├── src ├── App.vue ├── assets │ └── logo.png ├── components │ └── HelloWorld.vue ├── main.js ├── plugins │ └── rollup-plugin-upload-sourcemap.js └── utils │ └── monitor.js ├── vite.config.js └── yarn.lock /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 王振宇 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.en.md: -------------------------------------------------------------------------------- 1 | # Exception monitoring 2 | 3 | [简体中文](./README.md) | English 4 | 5 | #### Description 6 | 7 | Front-end exception monitoring Demo for Vue3 8 | 9 | #### Corresponding article 10 | 11 | [Vue3异常监控](https://juejin.cn/post/7019856167325630471) 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 异常监控 2 | 3 | 简体中文 | [English](./README.en.md) 4 | 5 | #### 介绍 6 | 7 | Vue3 前端异常监控系统 8 | 9 | #### 掘金对应文章 10 | 11 | [Vue3异常监控](https://juejin.cn/post/7019856167325630471) 12 | -------------------------------------------------------------------------------- /backend/.autod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | write: true, 5 | prefix: '^', 6 | plugin: 'autod-egg', 7 | test: [ 8 | 'test', 9 | 'benchmark', 10 | ], 11 | dep: [ 12 | 'egg', 13 | 'egg-scripts', 14 | ], 15 | devdep: [ 16 | 'egg-ci', 17 | 'egg-bin', 18 | 'egg-mock', 19 | 'autod', 20 | 'autod-egg', 21 | 'eslint', 22 | 'eslint-config-egg', 23 | ], 24 | exclude: [ 25 | './test/fixtures', 26 | './dist', 27 | ], 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /backend/.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | -------------------------------------------------------------------------------- /backend/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint-config-egg" 3 | } 4 | -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | npm-debug.log 3 | yarn-error.log 4 | yarn.lock 5 | run/ 6 | typings/ 7 | node_modules 8 | .DS_Store 9 | dist 10 | dist-ssr 11 | *.local 12 | upload/ -------------------------------------------------------------------------------- /backend/.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: node_js 3 | node_js: 4 | - '10' 5 | before_install: 6 | - npm i npminstall -g 7 | install: 8 | - npminstall 9 | script: 10 | - npm run ci 11 | after_script: 12 | - npminstall codecov && codecov 13 | -------------------------------------------------------------------------------- /backend/README.md: -------------------------------------------------------------------------------- 1 | # mointor-backend 2 | 3 | 4 | 5 | ## QuickStart 6 | 7 | 8 | 9 | see [egg docs][egg] for more detail. 10 | 11 | ### Development 12 | 13 | ```bash 14 | $ npm i 15 | $ npm run dev 16 | $ open http://localhost:7001/ 17 | ``` 18 | 19 | ### Deploy 20 | 21 | ```bash 22 | $ npm start 23 | $ npm stop 24 | ``` 25 | 26 | ### npm scripts 27 | 28 | - Use `npm run lint` to check code style. 29 | - Use `npm test` to run unit test. 30 | - Use `npm run autod` to auto detect dependencies upgrade, see [autod](https://www.npmjs.com/package/autod) for more detail. 31 | 32 | 33 | [egg]: https://eggjs.org -------------------------------------------------------------------------------- /backend/app/controller/home.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class HomeController extends Controller { 6 | async index() { 7 | const { ctx } = this; 8 | ctx.body = 'wzy test home'; 9 | } 10 | } 11 | 12 | module.exports = HomeController; 13 | -------------------------------------------------------------------------------- /backend/app/controller/mointor.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Controller = require('egg').Controller; 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const StackParser = require('../utils/stackparser'); 6 | const sendMail = require('../utils/sendMail'); 7 | 8 | class MointorController extends Controller { 9 | // 准备要上传的sourcemap的目标文件夹(没有则创建,如果有历史文件则清除) 10 | async emptyFolder() { 11 | const { ctx } = this; 12 | const env = ctx.query.env; 13 | const dir = path.join(this.config.baseDir, `upload/${env}`); 14 | // 判断upload/env文件夹是否存在 15 | if (!fs.existsSync(dir)) { 16 | // 没有创建 17 | fs.mkdirSync(dir); 18 | } else { 19 | // 有清空 20 | const files = fs.readdirSync(dir); 21 | files.forEach(file => { 22 | // 每一个文件路径 23 | const currentPath = dir + '/' + file; 24 | // 因为这里存放的都是.map文件,所以不需要判断是文件还是文件夹 25 | fs.unlinkSync(currentPath); 26 | }); 27 | } 28 | } 29 | // 前端打包时,上送sourcemap文件 30 | async uploadSourceMap() { 31 | const { ctx } = this; 32 | const stream = ctx.req, 33 | filename = ctx.query.name, 34 | env = ctx.query.env; 35 | // 要上传的目标路径 36 | const dir = path.join(this.config.baseDir, `upload/${env}`); 37 | // 目标文件 38 | const target = path.join(dir, filename); 39 | // 写入文件内容 40 | const writeStream = fs.createWriteStream(target); 41 | stream.pipe(writeStream); 42 | } 43 | // 前端报错,上报error 44 | async reportError() { 45 | const { ctx } = this; 46 | const { environment, location, message, stack, browserInfo, userId, userName, routerHistory, clickHistory } = ctx.request.body; 47 | let env = ''; 48 | if (environment === '测试环境') { 49 | env = 'uat'; 50 | } else if (environment === '生产环境') { 51 | env = 'prod'; 52 | } 53 | // 组合sourcemap文件路径 54 | const sourceMapDir = path.join(this.config.baseDir, `upload/${env}`); 55 | // 解析报错信息 56 | const stackParser = new StackParser(sourceMapDir); 57 | let routerHistoryStr = '

router history

', 58 | clickHistoryStr = '

click history

'; 59 | // 组合路由历史信息 60 | routerHistory && routerHistory.length && routerHistory.forEach(item => { 61 | routerHistoryStr += `

name:${item.name} | fullPath:${item.fullPath}

`; 62 | routerHistoryStr += `

params:${JSON.stringify(item.params)} | query:${JSON.stringify(item.query)}

--------------------

`; 63 | }); 64 | // 组合点击历史信息 65 | clickHistory && clickHistory.length && clickHistory.forEach(item => { 66 | clickHistoryStr += `

pageX:${item.pageX} | pageY:${item.pageY}

`; 67 | clickHistoryStr += `

nodeName:${item.nodeName} | className:${item.className} | id:${item.id}

`; 68 | clickHistoryStr += `

innerText:${item.innerText}

--------------------

`; 69 | }); 70 | // 通过上送的sourcemap文件,配合error信息,解析报错信息 71 | const errInfo = await stackParser.parseStackTrack(stack, message); 72 | console.log('errInfo', errInfo); 73 | // 获取当前时间 74 | const now = new Date(); 75 | const time = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()} ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`; 76 | // 组织邮件正文 77 | const mailMsg = ` 78 |

message:${message}

79 |

location:${location}

80 |

source:${errInfo.source}

81 |

line::${errInfo.lineNumber}

82 |

column:${errInfo.columnNumber}

83 |

fileName:${errInfo.fileName}

84 |

functionName:${errInfo.functionName}

85 |

time::${time}

86 |

browserInfo::${browserInfo}

87 |

userId::${userId}

88 |

userName::${userName}

89 | ${routerHistoryStr} 90 | ${clickHistoryStr} 91 | `; 92 | // sendMail('发件箱地址', '发件箱授权码', '收件箱地址', 主题 environment, 正文 mailMsg); 93 | sendMail('发件箱地址', '发件箱授权码', '收件箱地址', environment, mailMsg); 94 | ctx.body = { 95 | header: { 96 | code: 0, 97 | message: 'OK', 98 | }, 99 | }; 100 | ctx.status = 200; 101 | } 102 | } 103 | 104 | module.exports = MointorController; 105 | -------------------------------------------------------------------------------- /backend/app/middleware/error_handler.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = () => { 3 | return async function errorHandler(ctx, next) { 4 | try { 5 | await next(); 6 | } catch (err) { 7 | // 所有的异常都在 app 上触发一个 error 事件,框架会记录一条错误日志 8 | ctx.app.emit('error', err, ctx); 9 | 10 | const status = err.status || 500; 11 | // 生产环境时 500 错误的详细错误内容不返回给客户端,因为可能包含敏感信息 12 | const error = status === 500 && ctx.app.config.env === 'prod' 13 | ? 'Internal Server Error' 14 | : err.message; 15 | 16 | // 从 error 对象上读出各个属性,设置到响应中 17 | ctx.body = { error }; 18 | if (status === 422) { 19 | ctx.body.detail = err.errors; 20 | } 21 | ctx.status = status; 22 | } 23 | }; 24 | }; 25 | -------------------------------------------------------------------------------- /backend/app/router.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @param {Egg.Application} app - egg application 5 | */ 6 | module.exports = app => { 7 | const { router, controller } = app; 8 | router.get('/', controller.home.index); 9 | router.post('/mointor/reportError', controller.mointor.reportError); 10 | router.get('/mointor/emptyFolder', controller.mointor.emptyFolder); 11 | router.post('/mointor/uploadSourceMap', controller.mointor.uploadSourceMap); 12 | }; 13 | -------------------------------------------------------------------------------- /backend/app/utils/sendMail.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const nodemailer = require('nodemailer'); 3 | // 发送邮件方法 4 | function sendMail(from, fromPass, receivers, subject, msg) { 5 | const smtpTransport = nodemailer.createTransport({ 6 | host: 'smtp.qq.email', 7 | service: 'qq', 8 | secureConnection: true, // use SSL 9 | secure: true, 10 | port: 465, 11 | auth: { 12 | user: from, 13 | pass: fromPass, 14 | }, 15 | }); 16 | 17 | smtpTransport.sendMail({ 18 | from, 19 | // 收件人邮箱,多个邮箱地址间用英文逗号隔开 20 | to: receivers, 21 | // 邮件主题 22 | subject, 23 | // 邮件正文 24 | html: msg, 25 | }, err => { 26 | if (err) { 27 | console.log('send mail error: ', err); 28 | } 29 | }); 30 | } 31 | module.exports = sendMail; 32 | -------------------------------------------------------------------------------- /backend/app/utils/stackparser.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // 解析Error方法 3 | const ErrorStachParser = require('error-stack-parser'); 4 | const { SourceMapConsumer } = require('source-map'); 5 | const path = require('path'); 6 | const fs = require('fs'); 7 | module.exports = class StackParser { 8 | constructor(sourceMapDir) { 9 | this.sourceMapDir = sourceMapDir; 10 | this.consumers = {}; 11 | } 12 | async parseStackTrack(stack, message) { 13 | const error = new Error(message); 14 | error.stack = stack; 15 | // 获取error堆栈信息 16 | const stackFrame = ErrorStachParser.parse(error); 17 | return await this.getOriginalErrorStack(stackFrame); 18 | } 19 | // 获取原始错误堆栈信息 20 | async getOriginalErrorStack(stackFrame) { 21 | const origin = await this.getOriginPosition(stackFrame[0]); 22 | return origin; 23 | } 24 | async getOriginPosition(stackFrame) { 25 | let { columnNumber, lineNumber, fileName } = stackFrame; 26 | fileName = path.basename(fileName); 27 | // 判断consumer是否存在 28 | let consumer = this.consumers[fileName]; 29 | if (consumer === undefined) { 30 | // 读取sourcemap 31 | const sourceMapPath = path.resolve(this.sourceMapDir, fileName + '.map'); 32 | // 判断文件是否存在 33 | if (!fs.existsSync(sourceMapPath)) { 34 | return stackFrame; 35 | } 36 | // 获取sourcemap内容 37 | const content = fs.readFileSync(sourceMapPath, 'utf-8'); 38 | consumer = await new SourceMapConsumer(content, null); 39 | // 将本次获取的sourcemap对象存放在缓存,方便下次使用 40 | this.consumers[fileName] = consumer; 41 | } 42 | const parseData = consumer.originalPositionFor({ line: lineNumber, column: columnNumber }); 43 | return parseData; 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /backend/appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: '10' 4 | 5 | install: 6 | - ps: Install-Product node $env:nodejs_version 7 | - npm i npminstall && node_modules\.bin\npminstall 8 | 9 | test_script: 10 | - node --version 11 | - npm --version 12 | - npm run test 13 | 14 | build: off 15 | -------------------------------------------------------------------------------- /backend/config/config.default.js: -------------------------------------------------------------------------------- 1 | /* eslint valid-jsdoc: "off" */ 2 | 3 | 'use strict'; 4 | 5 | /** 6 | * @param {Egg.EggAppInfo} appInfo app info 7 | */ 8 | module.exports = appInfo => { 9 | /** 10 | * built-in config 11 | * @type {Egg.EggAppConfig} 12 | **/ 13 | const config = exports = {}; 14 | 15 | // use for cookie sign key, should change to your own and keep security 16 | config.keys = appInfo.name + '_1625466426614_2490'; 17 | 18 | // 跨域配置 19 | config.security = { 20 | csrf: false, 21 | debug: 'csrf-disable', 22 | domainWhiteList: [ 'http://localhost:8080', 'http://127.0.0.1:8080', 'http://127.0.0.1:5000' ], 23 | }; 24 | 25 | // add your middleware config here 26 | config.middleware = [ 'errorHandler' ]; 27 | config.errorHandler = { 28 | match: '/', 29 | }; 30 | 31 | // add your user config here 32 | const userConfig = { 33 | // myAppName: 'egg', 34 | }; 35 | 36 | return { 37 | ...config, 38 | ...userConfig, 39 | }; 40 | }; 41 | -------------------------------------------------------------------------------- /backend/config/plugin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** @type Egg.EggPlugin */ 4 | module.exports = { 5 | // had enabled by egg 6 | // static: { 7 | // enable: true, 8 | // } 9 | cors: { 10 | enable: true, 11 | package: 'egg-cors', 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /backend/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "**/*" 4 | ] 5 | } -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mointor-backend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "private": true, 6 | "egg": { 7 | "declarations": true 8 | }, 9 | "dependencies": { 10 | "egg": "^2.15.1", 11 | "egg-cors": "^2.2.3", 12 | "egg-scripts": "^2.11.0", 13 | "error-stack-parser": "^2.0.6", 14 | "nodemailer": "^6.6.2", 15 | "source-map": "^0.7.3" 16 | }, 17 | "devDependencies": { 18 | "autod": "^3.0.1", 19 | "autod-egg": "^1.1.0", 20 | "egg-bin": "^4.11.0", 21 | "egg-ci": "^1.11.0", 22 | "egg-mock": "^3.21.0", 23 | "eslint": "^5.13.0", 24 | "eslint-config-egg": "^7.1.0" 25 | }, 26 | "engines": { 27 | "node": ">=10.0.0" 28 | }, 29 | "scripts": { 30 | "start": "egg-scripts start --port=7001 --daemon --title=egg-server-mointor-backend", 31 | "stop": "egg-scripts stop --title=egg-server-mointor-backend", 32 | "dev": "egg-bin dev --port=7001", 33 | "debug": "egg-bin debug", 34 | "test": "npm run lint -- --fix && npm run test-local", 35 | "test-local": "egg-bin test", 36 | "cov": "egg-bin cov", 37 | "lint": "eslint .", 38 | "ci": "npm run lint && npm run cov", 39 | "autod": "autod" 40 | }, 41 | "ci": { 42 | "version": "10" 43 | }, 44 | "repository": { 45 | "type": "git", 46 | "url": "" 47 | }, 48 | "author": "", 49 | "license": "MIT" 50 | } 51 | -------------------------------------------------------------------------------- /vue-app/.env.development: -------------------------------------------------------------------------------- 1 | NODE_ENV = "development" 2 | VITE_BASE_API = "/development_base_api" 3 | # 本地测试异常监控用 4 | VITE_MONITOR_UPLOAD_API="http://127.0.0.1:7001/mointor" 5 | VITE_MONITOR_REPORT_API="/mointor" -------------------------------------------------------------------------------- /vue-app/.env.production: -------------------------------------------------------------------------------- 1 | NODE_ENV = "production" 2 | VITE_BASE_API = "production_base_api" 3 | VITE_MONITOR_UPLOAD_API="http://127.0.0.1:7001/mointor" 4 | VITE_MONITOR_REPORT_API="/mointor" -------------------------------------------------------------------------------- /vue-app/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local -------------------------------------------------------------------------------- /vue-app/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["johnsoncodehk.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /vue-app/README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + Vite 2 | 3 | This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 ` 12 | 13 | 14 | -------------------------------------------------------------------------------- /vue-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-app", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "serve": "vite preview" 9 | }, 10 | "dependencies": { 11 | "axios": "^0.22.0", 12 | "glob": "^7.2.0", 13 | "vue": "^3.2.16" 14 | }, 15 | "devDependencies": { 16 | "@vitejs/plugin-vue": "^1.9.3", 17 | "vite": "^2.6.4" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vue-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhenyuWang/Vue3-front-end--exception-monitoring/4b63694fe11b51c38ca50043dca017f5850d6bdf/vue-app/public/favicon.ico -------------------------------------------------------------------------------- /vue-app/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 19 | -------------------------------------------------------------------------------- /vue-app/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhenyuWang/Vue3-front-end--exception-monitoring/4b63694fe11b51c38ca50043dca017f5850d6bdf/vue-app/src/assets/logo.png -------------------------------------------------------------------------------- /vue-app/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 19 | 20 | 25 | -------------------------------------------------------------------------------- /vue-app/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import handleError from "./utils/monitor"; 4 | const app = createApp(App) 5 | // 异常监控上送报错信息 接口地址 6 | handleError(app, import.meta.env.VITE_MONITOR_REPORT_API); 7 | app.mount('#app') 8 | -------------------------------------------------------------------------------- /vue-app/src/plugins/rollup-plugin-upload-sourcemap.js: -------------------------------------------------------------------------------- 1 | import glob from "glob"; 2 | import path from "path"; 3 | import fs from "fs"; 4 | import http from "http"; 5 | export default function uploadSourceMap({ 6 | // 基础接口地址 7 | baseUrl, 8 | // 处理目标文件夹接口地址 9 | handleTargetFolderUrl, 10 | // 上传sourcemap文件地址 11 | uploadUrl, 12 | }) { 13 | return { 14 | name: "upload-sourcemap", 15 | // 打包完成后钩子 16 | closeBundle() { 17 | console.log('closeBundle'); 18 | // 获取当前环境 19 | let env = "uat"; 20 | if (baseUrl === "production_base_api") { 21 | env = "prod"; 22 | } 23 | // 上传文件方法 24 | function upload(url, file, env) { 25 | return new Promise((resolve) => { 26 | const req = http.request( 27 | `${url}?name=${path.basename(file)}&&env=${env}`, 28 | { 29 | method: "POST", 30 | headers: { 31 | "Content-Type": "application/octet-stream", 32 | Connection: "keep-alive", 33 | "Transfer-Encoding": "chunked", 34 | }, 35 | } 36 | ); 37 | // 读取文件并给到上送请求对象 38 | fs.createReadStream(file) 39 | .on("data", chunk => { 40 | req.write(chunk); 41 | }) 42 | .on("end", () => { 43 | req.end(); 44 | resolve("end"); 45 | }); 46 | }); 47 | } 48 | 49 | // 处理目标文件夹(没有创建,有则清空) 50 | function handleTargetFolder() { 51 | http 52 | .get(`${handleTargetFolderUrl}?env=${env}`, () => { 53 | console.log("handleTargetFolderUrl success"); 54 | }) 55 | .on("error", (e) => { 56 | console.log(`handle folder error: ${e.message}`); 57 | }); 58 | } 59 | handleTargetFolder(); 60 | // 读取sourcemap文件 上传并删除 61 | async function uploadDel() { 62 | const list = glob.sync(path.join("./dist", "./**/*.{js.map,}")); 63 | for (const filename of list) { 64 | await upload(uploadUrl, filename, env); 65 | await fs.unlinkSync(filename); 66 | } 67 | } 68 | uploadDel(); 69 | }, 70 | }; 71 | } 72 | -------------------------------------------------------------------------------- /vue-app/src/utils/monitor.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | // 获取浏览器信息 3 | function getBrowserInfo() { 4 | const agent = navigator.userAgent.toLowerCase(); 5 | const regIE = /msie [\d.]+;/gi; 6 | const regIE11 = /rv:[\d.]+/gi; 7 | const regFireFox = /firefox\/[\d.]+/gi; 8 | const regQQ = /qqbrowser\/[\d.]+/gi; 9 | const regEdg = /edg\/[\d.]+/gi; 10 | const regSafari = /safari\/[\d.]+/gi; 11 | const regChrome = /chrome\/[\d.]+/gi; 12 | // IE10及以下 13 | if (regIE.test(agent)) { 14 | return agent.match(regIE)[0]; 15 | } 16 | // IE11 17 | if (regIE11.test(agent)) { 18 | return "IE11"; 19 | } 20 | // firefox 21 | if (regFireFox.test(agent)) { 22 | return agent.match(regFireFox)[0]; 23 | } 24 | // QQ 25 | if (regQQ.test(agent)) { 26 | return agent.match(regQQ)[0]; 27 | } 28 | // Edg 29 | if (regEdg.test(agent)) { 30 | return agent.match(regEdg)[0]; 31 | } 32 | // Chrome 33 | if (regChrome.test(agent)) { 34 | return agent.match(regChrome)[0]; 35 | } 36 | // Safari 37 | if (regSafari.test(agent)) { 38 | return agent.match(regSafari)[0]; 39 | } 40 | } 41 | // 捕获报错方法 42 | export default function handleError(Vue,baseUrl) { 43 | if (!baseUrl) { 44 | console.log("baseUrl", baseUrl); 45 | return; 46 | } 47 | Vue.config.errorHandler = (err, vm) => { 48 | // 获取当前环境 49 | let environment = "测试环境"; 50 | if (import.meta.env.VITE_BASE_API === "production_base_api") { 51 | environment = "生产环境"; 52 | } 53 | // 发送请求上送报错信息 54 | axios({ 55 | method: "post", 56 | url: `${baseUrl}/reportError`, 57 | data: { 58 | environment, 59 | location: window.location.href, 60 | message: err.message, 61 | stack: err.stack, 62 | // 浏览器信息 63 | browserInfo: getBrowserInfo(), 64 | // 以下信息可以放在vuex store中维护 65 | // 用户ID 66 | userId:"001", 67 | // 用户名称 68 | userName:"张三", 69 | // 路由记录 70 | routerHistory:[ 71 | { 72 | fullPath:"/login", 73 | name:"Login", 74 | query:{}, 75 | params:{}, 76 | },{ 77 | fullPath:"/home", 78 | name:"Home", 79 | query:{}, 80 | params:{}, 81 | } 82 | ], 83 | // 点击记录 84 | clickHistory:[ 85 | { 86 | pageX:50, 87 | pageY:50, 88 | nodeName:"div", 89 | className:"test", 90 | id:"test", 91 | innerText:"测试按钮" 92 | } 93 | ], 94 | }, 95 | }); 96 | }; 97 | } 98 | -------------------------------------------------------------------------------- /vue-app/vite.config.js: -------------------------------------------------------------------------------- 1 | import { loadEnv } from "vite"; 2 | import vue from '@vitejs/plugin-vue' 3 | // 引入upload sourcemap rollup plugin 4 | import uploadSourceMap from "./src/plugins/rollup-plugin-upload-sourcemap"; 5 | 6 | // mode 当前环境 development production 7 | export default ({ mode }) => { 8 | const env = loadEnv(mode, process.cwd()); 9 | return { 10 | server: { 11 | open: true, 12 | port: 3000, 13 | host: "0.0.0.0", 14 | proxy: { 15 | // 本地测试异常监控用 16 | "/mointor": { 17 | target: 'http://127.0.0.1:7001', 18 | changeOrigin: true, 19 | }, 20 | }, 21 | }, 22 | plugins: [ 23 | vue(), 24 | // 使用upload sourcemap rollup plugin 25 | uploadSourceMap({ 26 | // 基本路径,判断当前环境使用 27 | baseUrl: env.VITE_BASE_API, 28 | // 处理目标文件夹接口地址 29 | handleTargetFolderUrl: `${env.VITE_MONITOR_UPLOAD_API}/emptyFolder`, 30 | // 上传sourcemap文件接口地址 31 | uploadUrl: `${env.VITE_MONITOR_UPLOAD_API}/uploadSourceMap`, 32 | }), 33 | ], 34 | build: { 35 | // 构建后是否生成 source map 文件 36 | sourcemap: true, 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /vue-app/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/parser@^7.15.0": 6 | version "7.15.8" 7 | resolved "https://registry.npmmirror.com/@babel/parser/download/@babel/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016" 8 | integrity sha1-e6zcvnG9w/+TbVEMFdzqfPC5kBY= 9 | 10 | "@vitejs/plugin-vue@^1.9.3": 11 | version "1.9.3" 12 | resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/download/@vitejs/plugin-vue-1.9.3.tgz#93d61893ce6c723d0209af0483ec8b91a2cd811f" 13 | integrity sha1-k9YYk85scj0CCa8Eg+yLkaLNgR8= 14 | 15 | "@vue/compiler-core@3.2.20": 16 | version "3.2.20" 17 | resolved "https://registry.npmmirror.com/@vue/compiler-core/download/@vue/compiler-core-3.2.20.tgz?cache=0&sync_timestamp=1633712761777&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40vue%2Fcompiler-core%2Fdownload%2F%40vue%2Fcompiler-core-3.2.20.tgz#af5a3c5237818835b0d0be837eb5885a8d21c160" 18 | integrity sha1-r1o8UjeBiDWw0L6DfrWIWo0hwWA= 19 | dependencies: 20 | "@babel/parser" "^7.15.0" 21 | "@vue/shared" "3.2.20" 22 | estree-walker "^2.0.2" 23 | source-map "^0.6.1" 24 | 25 | "@vue/compiler-dom@3.2.20": 26 | version "3.2.20" 27 | resolved "https://registry.npmmirror.com/@vue/compiler-dom/download/@vue/compiler-dom-3.2.20.tgz?cache=0&sync_timestamp=1633712762936&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40vue%2Fcompiler-dom%2Fdownload%2F%40vue%2Fcompiler-dom-3.2.20.tgz#8e0ef354449c0faf41519b00bfc2045eae01dcb5" 28 | integrity sha1-jg7zVEScD69BUZsAv8IEXq4B3LU= 29 | dependencies: 30 | "@vue/compiler-core" "3.2.20" 31 | "@vue/shared" "3.2.20" 32 | 33 | "@vue/compiler-sfc@3.2.20": 34 | version "3.2.20" 35 | resolved "https://registry.npmmirror.com/@vue/compiler-sfc/download/@vue/compiler-sfc-3.2.20.tgz?cache=0&sync_timestamp=1633712762379&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40vue%2Fcompiler-sfc%2Fdownload%2F%40vue%2Fcompiler-sfc-3.2.20.tgz#2d7668e76f066c566dd7c09c15c9acce4e876e0a" 36 | integrity sha1-LXZo528GbFZt18CcFcmszk6Hbgo= 37 | dependencies: 38 | "@babel/parser" "^7.15.0" 39 | "@vue/compiler-core" "3.2.20" 40 | "@vue/compiler-dom" "3.2.20" 41 | "@vue/compiler-ssr" "3.2.20" 42 | "@vue/ref-transform" "3.2.20" 43 | "@vue/shared" "3.2.20" 44 | estree-walker "^2.0.2" 45 | magic-string "^0.25.7" 46 | postcss "^8.1.10" 47 | source-map "^0.6.1" 48 | 49 | "@vue/compiler-ssr@3.2.20": 50 | version "3.2.20" 51 | resolved "https://registry.npmmirror.com/@vue/compiler-ssr/download/@vue/compiler-ssr-3.2.20.tgz?cache=0&sync_timestamp=1633712764229&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40vue%2Fcompiler-ssr%2Fdownload%2F%40vue%2Fcompiler-ssr-3.2.20.tgz#9cceb6261d9932cb5568202610c1c28f86c5e521" 52 | integrity sha1-nM62Jh2ZMstVaCAmEMHCj4bF5SE= 53 | dependencies: 54 | "@vue/compiler-dom" "3.2.20" 55 | "@vue/shared" "3.2.20" 56 | 57 | "@vue/reactivity@3.2.20": 58 | version "3.2.20" 59 | resolved "https://registry.npmmirror.com/@vue/reactivity/download/@vue/reactivity-3.2.20.tgz?cache=0&sync_timestamp=1633712763526&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40vue%2Freactivity%2Fdownload%2F%40vue%2Freactivity-3.2.20.tgz#81fe1c368e7f20bc0ec1dec1045bbee253582de8" 60 | integrity sha1-gf4cNo5/ILwOwd7BBFu+4lNYLeg= 61 | dependencies: 62 | "@vue/shared" "3.2.20" 63 | 64 | "@vue/ref-transform@3.2.20": 65 | version "3.2.20" 66 | resolved "https://registry.npmmirror.com/@vue/ref-transform/download/@vue/ref-transform-3.2.20.tgz?cache=0&sync_timestamp=1633712763825&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40vue%2Fref-transform%2Fdownload%2F%40vue%2Fref-transform-3.2.20.tgz#2a59ec90caf8e5c7336776a0900bff0a8b81c090" 67 | integrity sha1-KlnskMr45cczZ3agkAv/CouBwJA= 68 | dependencies: 69 | "@babel/parser" "^7.15.0" 70 | "@vue/compiler-core" "3.2.20" 71 | "@vue/shared" "3.2.20" 72 | estree-walker "^2.0.2" 73 | magic-string "^0.25.7" 74 | 75 | "@vue/runtime-core@3.2.20": 76 | version "3.2.20" 77 | resolved "https://registry.npmmirror.com/@vue/runtime-core/download/@vue/runtime-core-3.2.20.tgz?cache=0&sync_timestamp=1633712764609&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40vue%2Fruntime-core%2Fdownload%2F%40vue%2Fruntime-core-3.2.20.tgz#8f63e956a3f88fb772541443c45a7701211012cb" 78 | integrity sha1-j2PpVqP4j7dyVBRDxFp3ASEQEss= 79 | dependencies: 80 | "@vue/reactivity" "3.2.20" 81 | "@vue/shared" "3.2.20" 82 | 83 | "@vue/runtime-dom@3.2.20": 84 | version "3.2.20" 85 | resolved "https://registry.npmmirror.com/@vue/runtime-dom/download/@vue/runtime-dom-3.2.20.tgz?cache=0&sync_timestamp=1633712766458&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40vue%2Fruntime-dom%2Fdownload%2F%40vue%2Fruntime-dom-3.2.20.tgz#8aa56ae6c30f9cd4a71ca0e9ec3c4bdc67148d15" 86 | integrity sha1-iqVq5sMPnNSnHKDp7DxL3GcUjRU= 87 | dependencies: 88 | "@vue/runtime-core" "3.2.20" 89 | "@vue/shared" "3.2.20" 90 | csstype "^2.6.8" 91 | 92 | "@vue/server-renderer@3.2.20": 93 | version "3.2.20" 94 | resolved "https://registry.npmmirror.com/@vue/server-renderer/download/@vue/server-renderer-3.2.20.tgz?cache=0&sync_timestamp=1633712766117&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40vue%2Fserver-renderer%2Fdownload%2F%40vue%2Fserver-renderer-3.2.20.tgz#705e07ae9425132b2b6227d308a51a13f4d4ec81" 95 | integrity sha1-cF4HrpQlEysrYifTCKUaE/TU7IE= 96 | dependencies: 97 | "@vue/compiler-ssr" "3.2.20" 98 | "@vue/shared" "3.2.20" 99 | 100 | "@vue/shared@3.2.20": 101 | version "3.2.20" 102 | resolved "https://registry.npmmirror.com/@vue/shared/download/@vue/shared-3.2.20.tgz?cache=0&sync_timestamp=1633712765807&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40vue%2Fshared%2Fdownload%2F%40vue%2Fshared-3.2.20.tgz#53746961f731a8ea666e3316271e944238dc31db" 103 | integrity sha1-U3RpYfcxqOpmbjMWJx6UQjjcMds= 104 | 105 | axios@^0.22.0: 106 | version "0.22.0" 107 | resolved "https://registry.npmmirror.com/axios/download/axios-0.22.0.tgz#bf702c41fb50fbca4539589d839a077117b79b25" 108 | integrity sha1-v3AsQftQ+8pFOVidg5oHcRe3myU= 109 | dependencies: 110 | follow-redirects "^1.14.4" 111 | 112 | balanced-match@^1.0.0: 113 | version "1.0.2" 114 | resolved "https://registry.nlark.com/balanced-match/download/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 115 | integrity sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4= 116 | 117 | brace-expansion@^1.1.7: 118 | version "1.1.11" 119 | resolved "https://registry.nlark.com/brace-expansion/download/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 120 | integrity sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0= 121 | dependencies: 122 | balanced-match "^1.0.0" 123 | concat-map "0.0.1" 124 | 125 | concat-map@0.0.1: 126 | version "0.0.1" 127 | resolved "https://registry.nlark.com/concat-map/download/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 128 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 129 | 130 | csstype@^2.6.8: 131 | version "2.6.18" 132 | resolved "https://registry.nlark.com/csstype/download/csstype-2.6.18.tgz?cache=0&sync_timestamp=1631540782346&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcsstype%2Fdownload%2Fcsstype-2.6.18.tgz#980a8b53085f34af313410af064f2bd241784218" 133 | integrity sha1-mAqLUwhfNK8xNBCvBk8r0kF4Qhg= 134 | 135 | esbuild-android-arm64@0.13.4: 136 | version "0.13.4" 137 | resolved "https://registry.npmmirror.com/esbuild-android-arm64/download/esbuild-android-arm64-0.13.4.tgz?cache=0&sync_timestamp=1633444875975&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-android-arm64%2Fdownload%2Fesbuild-android-arm64-0.13.4.tgz#5178a20d2b7aba741a31c19609f9e67b346996b9" 138 | integrity sha1-UXiiDSt6unQaMcGWCfnmezRplrk= 139 | 140 | esbuild-darwin-64@0.13.4: 141 | version "0.13.4" 142 | resolved "https://registry.npmmirror.com/esbuild-darwin-64/download/esbuild-darwin-64-0.13.4.tgz?cache=0&sync_timestamp=1633444867046&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-darwin-64%2Fdownload%2Fesbuild-darwin-64-0.13.4.tgz#7a3e66c8e1271b650541b25eed65c84f3564a69d" 143 | integrity sha1-ej5myOEnG2UFQbJe7WXITzVkpp0= 144 | 145 | esbuild-darwin-arm64@0.13.4: 146 | version "0.13.4" 147 | resolved "https://registry.npmmirror.com/esbuild-darwin-arm64/download/esbuild-darwin-arm64-0.13.4.tgz?cache=0&sync_timestamp=1633444861721&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-darwin-arm64%2Fdownload%2Fesbuild-darwin-arm64-0.13.4.tgz#793feca6032b2a57ef291eb9b2d33768d60a49d6" 148 | integrity sha1-eT/spgMrKlfvKR65stM3aNYKSdY= 149 | 150 | esbuild-freebsd-64@0.13.4: 151 | version "0.13.4" 152 | resolved "https://registry.npmmirror.com/esbuild-freebsd-64/download/esbuild-freebsd-64-0.13.4.tgz?cache=0&sync_timestamp=1633444868225&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-freebsd-64%2Fdownload%2Fesbuild-freebsd-64-0.13.4.tgz#294aec3c2cf4b41fb6900212fc9c33dd8fbbb4a2" 153 | integrity sha1-KUrsPCz0tB+2kAIS/Jwz3Y+7tKI= 154 | 155 | esbuild-freebsd-arm64@0.13.4: 156 | version "0.13.4" 157 | resolved "https://registry.npmmirror.com/esbuild-freebsd-arm64/download/esbuild-freebsd-arm64-0.13.4.tgz?cache=0&sync_timestamp=1633444861720&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-freebsd-arm64%2Fdownload%2Fesbuild-freebsd-arm64-0.13.4.tgz#09fe66c751c12f9b976976b1d83f3de594cb2787" 158 | integrity sha1-Cf5mx1HBL5uXaXax2D895ZTLJ4c= 159 | 160 | esbuild-linux-32@0.13.4: 161 | version "0.13.4" 162 | resolved "https://registry.npmmirror.com/esbuild-linux-32/download/esbuild-linux-32-0.13.4.tgz?cache=0&sync_timestamp=1633444872215&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-linux-32%2Fdownload%2Fesbuild-linux-32-0.13.4.tgz#a9f0793d7bcc9cef4f4ffa4398c525877fba5839" 163 | integrity sha1-qfB5PXvMnO9PT/pDmMUlh3+6WDk= 164 | 165 | esbuild-linux-64@0.13.4: 166 | version "0.13.4" 167 | resolved "https://registry.npmmirror.com/esbuild-linux-64/download/esbuild-linux-64-0.13.4.tgz?cache=0&sync_timestamp=1633444883490&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-linux-64%2Fdownload%2Fesbuild-linux-64-0.13.4.tgz#c0d0b4c9d62e3bbf8bdf2cece37403aa6d60fc2e" 168 | integrity sha1-wNC0ydYuO7+L3yzs43QDqm1g/C4= 169 | 170 | esbuild-linux-arm64@0.13.4: 171 | version "0.13.4" 172 | resolved "https://registry.npmmirror.com/esbuild-linux-arm64/download/esbuild-linux-arm64-0.13.4.tgz?cache=0&sync_timestamp=1633444868914&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-linux-arm64%2Fdownload%2Fesbuild-linux-arm64-0.13.4.tgz#1292d97bfa64a08d12728f8a7837bf92776c779b" 173 | integrity sha1-EpLZe/pkoI0Sco+KeDe/kndsd5s= 174 | 175 | esbuild-linux-arm@0.13.4: 176 | version "0.13.4" 177 | resolved "https://registry.npmmirror.com/esbuild-linux-arm/download/esbuild-linux-arm-0.13.4.tgz?cache=0&sync_timestamp=1633444879917&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-linux-arm%2Fdownload%2Fesbuild-linux-arm-0.13.4.tgz#186cd9b8885ac132b9953a4a0afe668168debd10" 178 | integrity sha1-GGzZuIhawTK5lTpKCv5mgWjevRA= 179 | 180 | esbuild-linux-mips64le@0.13.4: 181 | version "0.13.4" 182 | resolved "https://registry.npmmirror.com/esbuild-linux-mips64le/download/esbuild-linux-mips64le-0.13.4.tgz?cache=0&sync_timestamp=1633444888556&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-linux-mips64le%2Fdownload%2Fesbuild-linux-mips64le-0.13.4.tgz#42049bf72bc586817b4a51cc9e32148d13e5e807" 183 | integrity sha1-QgSb9yvFhoF7SlHMnjIUjRPl6Ac= 184 | 185 | esbuild-linux-ppc64le@0.13.4: 186 | version "0.13.4" 187 | resolved "https://registry.npmmirror.com/esbuild-linux-ppc64le/download/esbuild-linux-ppc64le-0.13.4.tgz?cache=0&sync_timestamp=1633444868959&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-linux-ppc64le%2Fdownload%2Fesbuild-linux-ppc64le-0.13.4.tgz#adf1ce2ef2302757c4383887da6ac4dd25be9d4f" 188 | integrity sha1-rfHOLvIwJ1fEODiH2mrE3SW+nU8= 189 | 190 | esbuild-openbsd-64@0.13.4: 191 | version "0.13.4" 192 | resolved "https://registry.npmmirror.com/esbuild-openbsd-64/download/esbuild-openbsd-64-0.13.4.tgz?cache=0&sync_timestamp=1633444889167&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-openbsd-64%2Fdownload%2Fesbuild-openbsd-64-0.13.4.tgz#1c8122101898c52a20c8786935cf3eb7a19b83b4" 193 | integrity sha1-HIEiEBiYxSogyHhpNc8+t6Gbg7Q= 194 | 195 | esbuild-sunos-64@0.13.4: 196 | version "0.13.4" 197 | resolved "https://registry.npmmirror.com/esbuild-sunos-64/download/esbuild-sunos-64-0.13.4.tgz?cache=0&sync_timestamp=1633444866334&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-sunos-64%2Fdownload%2Fesbuild-sunos-64-0.13.4.tgz#4ec95faa14a60f295fe485bebffefff408739337" 198 | integrity sha1-TslfqhSmDylf5IW+v/7/9Ahzkzc= 199 | 200 | esbuild-windows-32@0.13.4: 201 | version "0.13.4" 202 | resolved "https://registry.npmmirror.com/esbuild-windows-32/download/esbuild-windows-32-0.13.4.tgz?cache=0&sync_timestamp=1633444889847&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-windows-32%2Fdownload%2Fesbuild-windows-32-0.13.4.tgz#3182c380487b797b04d0ec2c80c2945666869080" 203 | integrity sha1-MYLDgEh7eXsE0OwsgMKUVmaGkIA= 204 | 205 | esbuild-windows-64@0.13.4: 206 | version "0.13.4" 207 | resolved "https://registry.npmmirror.com/esbuild-windows-64/download/esbuild-windows-64-0.13.4.tgz?cache=0&sync_timestamp=1633444890802&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-windows-64%2Fdownload%2Fesbuild-windows-64-0.13.4.tgz#b9e995f92d81f433a04f33611e603e82f9232e69" 208 | integrity sha1-uemV+S2B9DOgTzNhHmA+gvkjLmk= 209 | 210 | esbuild-windows-arm64@0.13.4: 211 | version "0.13.4" 212 | resolved "https://registry.npmmirror.com/esbuild-windows-arm64/download/esbuild-windows-arm64-0.13.4.tgz?cache=0&sync_timestamp=1633444887993&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild-windows-arm64%2Fdownload%2Fesbuild-windows-arm64-0.13.4.tgz#fb239532f07b764d158f4cc787178ef4c6fadb5c" 213 | integrity sha1-+yOVMvB7dk0Vj0zHhxeO9Mb621w= 214 | 215 | esbuild@^0.13.2: 216 | version "0.13.4" 217 | resolved "https://registry.npmmirror.com/esbuild/download/esbuild-0.13.4.tgz?cache=0&sync_timestamp=1633444872095&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fesbuild%2Fdownload%2Fesbuild-0.13.4.tgz#ce2deb56c4fb360938311cbfc67f8e467bb6841b" 218 | integrity sha1-zi3rVsT7Ngk4MRy/xn+ORnu2hBs= 219 | optionalDependencies: 220 | esbuild-android-arm64 "0.13.4" 221 | esbuild-darwin-64 "0.13.4" 222 | esbuild-darwin-arm64 "0.13.4" 223 | esbuild-freebsd-64 "0.13.4" 224 | esbuild-freebsd-arm64 "0.13.4" 225 | esbuild-linux-32 "0.13.4" 226 | esbuild-linux-64 "0.13.4" 227 | esbuild-linux-arm "0.13.4" 228 | esbuild-linux-arm64 "0.13.4" 229 | esbuild-linux-mips64le "0.13.4" 230 | esbuild-linux-ppc64le "0.13.4" 231 | esbuild-openbsd-64 "0.13.4" 232 | esbuild-sunos-64 "0.13.4" 233 | esbuild-windows-32 "0.13.4" 234 | esbuild-windows-64 "0.13.4" 235 | esbuild-windows-arm64 "0.13.4" 236 | 237 | estree-walker@^2.0.2: 238 | version "2.0.2" 239 | resolved "https://registry.npm.taobao.org/estree-walker/download/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" 240 | integrity sha1-UvAQF4wqTBF6d1fP6UKtt9LaTKw= 241 | 242 | follow-redirects@^1.14.4: 243 | version "1.14.4" 244 | resolved "https://registry.nlark.com/follow-redirects/download/follow-redirects-1.14.4.tgz?cache=0&sync_timestamp=1631622206750&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffollow-redirects%2Fdownload%2Ffollow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" 245 | integrity sha1-g4/fSKi73XnlLuUfsclOPtmLk3k= 246 | 247 | fs.realpath@^1.0.0: 248 | version "1.0.0" 249 | resolved "https://registry.nlark.com/fs.realpath/download/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 250 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 251 | 252 | fsevents@~2.3.2: 253 | version "2.3.2" 254 | resolved "https://registry.npm.taobao.org/fsevents/download/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 255 | integrity sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro= 256 | 257 | function-bind@^1.1.1: 258 | version "1.1.1" 259 | resolved "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 260 | integrity sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0= 261 | 262 | glob@^7.2.0: 263 | version "7.2.0" 264 | resolved "https://registry.npmmirror.com/glob/download/glob-7.2.0.tgz?cache=0&sync_timestamp=1632353796482&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fglob%2Fdownload%2Fglob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" 265 | integrity sha1-0VU1r3cy4C6Uj0xBYovZECk/YCM= 266 | dependencies: 267 | fs.realpath "^1.0.0" 268 | inflight "^1.0.4" 269 | inherits "2" 270 | minimatch "^3.0.4" 271 | once "^1.3.0" 272 | path-is-absolute "^1.0.0" 273 | 274 | has@^1.0.3: 275 | version "1.0.3" 276 | resolved "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 277 | integrity sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y= 278 | dependencies: 279 | function-bind "^1.1.1" 280 | 281 | inflight@^1.0.4: 282 | version "1.0.6" 283 | resolved "https://registry.nlark.com/inflight/download/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 284 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 285 | dependencies: 286 | once "^1.3.0" 287 | wrappy "1" 288 | 289 | inherits@2: 290 | version "2.0.4" 291 | resolved "https://registry.nlark.com/inherits/download/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 292 | integrity sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w= 293 | 294 | is-core-module@^2.2.0: 295 | version "2.7.0" 296 | resolved "https://registry.npmmirror.com/is-core-module/download/is-core-module-2.7.0.tgz#3c0ef7d31b4acfc574f80c58409d568a836848e3" 297 | integrity sha1-PA730xtKz8V0+AxYQJ1WioNoSOM= 298 | dependencies: 299 | has "^1.0.3" 300 | 301 | magic-string@^0.25.7: 302 | version "0.25.7" 303 | resolved "https://registry.npm.taobao.org/magic-string/download/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" 304 | integrity sha1-P0l9b9NMZpxnmNy4IfLvMfVEUFE= 305 | dependencies: 306 | sourcemap-codec "^1.4.4" 307 | 308 | minimatch@^3.0.4: 309 | version "3.0.4" 310 | resolved "https://registry.nlark.com/minimatch/download/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 311 | integrity sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM= 312 | dependencies: 313 | brace-expansion "^1.1.7" 314 | 315 | nanoid@^3.1.28: 316 | version "3.1.29" 317 | resolved "https://registry.npmmirror.com/nanoid/download/nanoid-3.1.29.tgz?cache=0&sync_timestamp=1633468213445&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fnanoid%2Fdownload%2Fnanoid-3.1.29.tgz#214fb2d7a33e1a5bef4757b779dfaeb6a4e5aeb4" 318 | integrity sha1-IU+y16M+GlvvR1e3ed+utqTlrrQ= 319 | 320 | once@^1.3.0: 321 | version "1.4.0" 322 | resolved "https://registry.nlark.com/once/download/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 323 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 324 | dependencies: 325 | wrappy "1" 326 | 327 | path-is-absolute@^1.0.0: 328 | version "1.0.1" 329 | resolved "https://registry.nlark.com/path-is-absolute/download/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 330 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 331 | 332 | path-parse@^1.0.6: 333 | version "1.0.7" 334 | resolved "https://registry.nlark.com/path-parse/download/path-parse-1.0.7.tgz?cache=0&sync_timestamp=1621947783503&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpath-parse%2Fdownload%2Fpath-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 335 | integrity sha1-+8EUtgykKzDZ2vWFjkvWi77bZzU= 336 | 337 | picocolors@^0.2.1: 338 | version "0.2.1" 339 | resolved "https://registry.npmmirror.com/picocolors/download/picocolors-0.2.1.tgz?cache=0&sync_timestamp=1633377721334&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fpicocolors%2Fdownload%2Fpicocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" 340 | integrity sha1-VwZw95NkaFHRuhNZlpYqutWHhZ8= 341 | 342 | postcss@^8.1.10, postcss@^8.3.8: 343 | version "8.3.9" 344 | resolved "https://registry.npmmirror.com/postcss/download/postcss-8.3.9.tgz?cache=0&sync_timestamp=1633378564902&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fpostcss%2Fdownload%2Fpostcss-8.3.9.tgz#98754caa06c4ee9eb59cc48bd073bb6bd3437c31" 345 | integrity sha1-mHVMqgbE7p61nMSL0HO7a9NDfDE= 346 | dependencies: 347 | nanoid "^3.1.28" 348 | picocolors "^0.2.1" 349 | source-map-js "^0.6.2" 350 | 351 | resolve@^1.20.0: 352 | version "1.20.0" 353 | resolved "https://registry.npm.taobao.org/resolve/download/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" 354 | integrity sha1-YpoBP7P3B1XW8LeTXMHCxTeLGXU= 355 | dependencies: 356 | is-core-module "^2.2.0" 357 | path-parse "^1.0.6" 358 | 359 | rollup@^2.57.0: 360 | version "2.58.0" 361 | resolved "https://registry.npmmirror.com/rollup/download/rollup-2.58.0.tgz#a643983365e7bf7f5b7c62a8331b983b7c4c67fb" 362 | integrity sha1-pkOYM2Xnv39bfGKoMxuYO3xMZ/s= 363 | optionalDependencies: 364 | fsevents "~2.3.2" 365 | 366 | source-map-js@^0.6.2: 367 | version "0.6.2" 368 | resolved "https://registry.npm.taobao.org/source-map-js/download/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" 369 | integrity sha1-C7XeYxtBz72mz7qL0FqA79/SOF4= 370 | 371 | source-map@^0.6.1: 372 | version "0.6.1" 373 | resolved "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 374 | integrity sha1-dHIq8y6WFOnCh6jQu95IteLxomM= 375 | 376 | sourcemap-codec@^1.4.4: 377 | version "1.4.8" 378 | resolved "https://registry.nlark.com/sourcemap-codec/download/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" 379 | integrity sha1-6oBL2UhXQC5pktBaOO8a41qatMQ= 380 | 381 | vite@^2.6.4: 382 | version "2.6.7" 383 | resolved "https://registry.npmmirror.com/vite/download/vite-2.6.7.tgz#e15c1d8327950720b5d7c4ec3fb36a5a58ccf7cb" 384 | integrity sha1-4VwdgyeVByC118TsP7NqWljM98s= 385 | dependencies: 386 | esbuild "^0.13.2" 387 | postcss "^8.3.8" 388 | resolve "^1.20.0" 389 | rollup "^2.57.0" 390 | optionalDependencies: 391 | fsevents "~2.3.2" 392 | 393 | vue@^3.2.16: 394 | version "3.2.20" 395 | resolved "https://registry.npmmirror.com/vue/download/vue-3.2.20.tgz?cache=0&sync_timestamp=1633712767060&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fvue%2Fdownload%2Fvue-3.2.20.tgz#940f8aa8bf3e3be78243ca582bad41fcd45ae3e6" 396 | integrity sha1-lA+KqL8+O+eCQ8pYK61B/NRa4+Y= 397 | dependencies: 398 | "@vue/compiler-dom" "3.2.20" 399 | "@vue/compiler-sfc" "3.2.20" 400 | "@vue/runtime-dom" "3.2.20" 401 | "@vue/server-renderer" "3.2.20" 402 | "@vue/shared" "3.2.20" 403 | 404 | wrappy@1: 405 | version "1.0.2" 406 | resolved "https://registry.nlark.com/wrappy/download/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 407 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 408 | --------------------------------------------------------------------------------