vue中重写并自定义console.log
0. 背景
在vue2项目中自定义console.log并输出文件名及行、列号
1. 实现
1.1 自定义console.log

export default {// 输出等级: 0-no, 1-error, 2-warning, 3-info, 4-debug, 5-loglevel: 5,// 输出模式: 0-default, 1-normal, 2-randommode: 1,// 是否输出图标hasIcon: false,// 是否在vue内使用isVue: true,// 是否打印函数名和所在文件行号isPrintLine: true,// 图标icons: ['🌵', '🎍', '🐾', '🌀', '🐚', '🥝', '🥜', '🥕', '🥒', '🌽', '🍒', '🍅', '🍑', '🍋', '🍈', '🌶', '🌰', '🍠', '🍆', '🍄', '🍐', '🍌', '🍍', '🍇', '🍏', '🍓', '🍎', '🍊', '🐴', '🐗', '🦄', '🐑', '🐶', '🐔', '🐼', '🐒', '🌝', '💄', '💋', '👠', '👗', '👙', '🧣', '🍰', '🍭', '🍳', '🎄', '🎱', '⚽', '🏀', '🎵', '🚄', '⭕', '❌', '❓', '❗', '💯'],// 标准颜色colors: {error: '#f7630c',warning: '#ca5010',info: '#0078d7',debug: '#13a10e',log: '#1f1f1f'},// 获取随机图标randomIcon: function () {return this.icons[Math.floor(Math.random() * this.icons.length)]},// 获取随机颜色randomColor: function () {const r = Math.floor(Math.random() * 256)const g = Math.floor(Math.random() * 256)const b = Math.floor(Math.random() * 256)// 返回随机生成的颜色return `rgb(${r}, ${g}, ${b})`},// 默认打印printDefault: function (tag, args) {console.log(tag, ...args)},// 标准打印printNormal: function (tag, args) {console.log(`%c ${tag} : `, `color: ${this.colors[tag]}`, ...args)},// 随机打印printRandom: function (tag, args) {const icon = this.randomIcon()const bgColor = this.randomColor()const color = this.randomColor()console.log(`%c ${icon}`, `font-size:20px;background-color: ${bgColor};color: ${color};`, tag + ' : ', ...args)},print: function (tag, args) {if (this.isPrintLine) {if (!this.isVue) {// 获取函数名和行号const err = new Error()// console.log(err.stack)const stack = err.stack.split('\n').slice(3).map(line => line.trim())// console.log(stack)const caller = stack[0].match(/at (.+) \(/) ? stack[0].match(/at (.+) \(/)[1] : stack[0].match(/at (.+):\d+:/)[1]const fileLine = stack[0].match(/\(.*\/(.+)\)/) ? stack[0].match(/\(.*\/(.+)\)/)[1] : stack[0].match(/(\d+:\d+)/)[1]// console.log(`${caller} (${fileLine}):\n`)args.shift(`[${caller} (${fileLine})]\n`)} else {args.shift()}} else {if (this.isVue) {args.shift().shift()}}switch (this.mode) {case 0: {this.printDefault(tag, args)break}case 1: {this.printNormal(tag, args)break}case 2: {this.printRandom(tag, args)break}}},error: (function (oriLogFunc) {return function (...args) {const tag = 'error'if (this.level >= 1) {// oriLogFunc.call(console, 'error : ', args)this.print(tag, args)}}})(console.log),warning: (function (oriLogFunc) {return function (...args) {const tag = 'warning'if (this.level >= 2) {// oriLogFunc.call(console, 'warning : ', args)this.print(tag, args)}}})(console.log),info: (function (oriLogFunc) {return function (...args) {const tag = 'info'if (this.level >= 3) {// oriLogFunc.call(console, 'info : ', args)this.print(tag, args)}}})(console.log),debug: (function (oriLogFunc) {return function (...args) {const tag = 'debug'if (this.level >= 4) {// oriLogFunc.call(console, 'debug : ', ...args)this.print(tag, args)}}})(console.log),log: (function (oriLogFunc) {return function (...args) {const tag = 'log'if (this.level >= 5) {// oriLogFunc.call(console, 'log : ', ...args)this.print(tag, args)}}})(console.log)
}
1.2 webpack记录行号
添加自定义
loader

module.exports = function (content) {content = content.toString('utf-8')if (this.cacheable) this.cacheable()const { name = ['this.\\$iceLog.log'] } = this.query.config || {}const fileName = this.resourcePath.replaceAll('\\', '/').match(/(?<=\/)(src.*)/gm)[0]content = content.split('\n').map((line, row) => {let loggerName = name[0]for (let i = 1; i < name.length; i++) {loggerName += '|' + name[i]}const re = new RegExp(`(${loggerName})\\((.*?)\\)`, 'g')let resultlet newLine = ''let cursor = 0while ((result = re.exec(line))) {const col = result.indexnewLine += line.slice(cursor, result.index) + `${result[1]}('[${fileName}:${row + 1}:${col + 1}]\\n', ` + result[2] + ')'cursor += col + result[0].length}newLine += line.slice(cursor)return newLine}).join('\n')return content
}
module.exports.raw = true
1.3 配置loader
修改
vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({transpileDependencies: true,lintOnSave: false,chainWebpack: config => {// config.devtool('eval-cheap-module-source-map')config.module.rule('vue').use('vue-loader').end().rule('log-lineno').use('./loaders/log-lineno.loader').loader('./loaders/log-lineno.loader').options({config: {name: ['this.\\$iceLog.error','this.\\$iceLog.warning','this.\\$iceLog.info','this.\\$iceLog.debug','this.\\$iceLog.log']}}).end()}
})
2. 测试
created () {this.$iceLog.log(123)this.$iceLog.error(1, 2, 3, 4)},

3. 问题
3.1 .vue文件被编译多次,自定义log会输出两个目录

解决:
在自定义函数中移除一个参数:

x. 参考
- 重写并自定义console.log()输出样式
- 巧用 webpack 在日志中记录文件行号
- vue webpace相关
- Vue2工程化 webpack配置 loader插件
- webpack初学者看这篇就够了
- 你了解webpack中配置的loader的执行顺序吗?
相关文章:
vue中重写并自定义console.log
0. 背景 在vue2项目中自定义console.log并输出文件名及行、列号 1. 实现 1.1 自定义console.log export default {// 输出等级: 0-no, 1-error, 2-warning, 3-info, 4-debug, 5-loglevel: 5,// 输出模式: 0-default, 1-normal, 2-randommode: 1,// 是否输出图标hasIcon: fal…...
基于OpenCV 和 Dlib 进行头部姿态估计
写在前面 工作中遇到,简单整理博文内容涉及基于 OpenCV 和 Dlib头部姿态评估的简单Demo理解不足小伙伴帮忙指正 庐山烟雨浙江潮,未到千般恨不消。到得还来别无事,庐山烟雨浙江潮。 ----《庐山烟雨浙江潮》苏轼 https://github.com/LIRUILONGS…...
24个Jvm面试题总结及答案
1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每…...
freemarker 生成前端文件
Freemarker是一种模板引擎,它允许我们在Java应用程序中分离视图和业务逻辑。在Freemarker中,List是一种非常有用的数据结构,它允许我们存储一组有序的元素。有时候,我们需要判断一个List是否为空,这在程序设计中有许多…...
Pycharm+pytest+allure打造高逼格的测试报告
目录 前言: 1、安装allure 2、安装allure-pytest 3、一个简单的用例test_simpe.py 4、在pycharm底部打开terminal 5、用allure美化报告 6、查看报告 总结: 前言: 今天分享的内容:在Pycharmpytest基础上使用allure打造高逼格…...
Mybatis-Plus中update更新操作用法
目录 一、前言二、update1、关于修改的4个条件构造器2、UpdateWrapper【用法示例】3、LambdaUpdateWrapper【用法示例】4、UpdateChainWrapper【 用法示例】5、LambdaUpdateChainWrapper【 用法示例】6、updateById 和 updateBatchById7、Mybatis-plus设置某个字段值为null的方…...
16道JVM面试题
1.jvm内存布局 1.程序计数器:当前线程正在执行的字节码的行号指示器,线程私有,唯一一个没有规定任何内存溢出错误的情况的区域。 2.Java虚拟机栈:线程私有,描述Java方法执行的内存模型,每个方法运行时都会…...
HttpRunner 接口自动化测试框架实战,打造高效测试流程
简介 2018年python开发者大会上,了解到HttpRuuner开源自动化测试框架,采用YAML/JSON格式管理用例,能录制和转换生成用例功能,充分做到用例与测试代码分离,相比excel维护测试场景数据更加简洁。在此,利用业…...
手写一个webpack插件(plugin)
熟悉 vue 和 react 的小伙伴们都知道,在执行过程中会有各种生命周期钩子,其实webpack也不例外,在使用webpack的时候,我们有时候需要在 webpack 构建流程中引入自定义的行为,这个时候就可以在 hooks 钩子中添加自己的方…...
jvm常见面试题
0x01. 内存模型以及分区,需要详细到每个区放什么。 栈区: 栈分为java虚拟机栈和本地方法栈 重点是Java虚拟机栈,它是线程私有的,生命周期与线程相同。 每个方法执行都会创建一个栈帧,用于存放局部变量表࿰…...
TF-A 项目的长期支持介绍
引流关键词:Armv8-A, Armv9-A, Cortex-A, Cortex-A12, Cortex-A15, Cortex-A17, Cortex-A32, Cortex-A34, Cortex-A35, Cortex-A5, Cortex-A510, Cortex-A53, Cortex-A55, Cortex-A57, Cortex-A65, Cortex-A65AE, Cortex-A7, Cortex-A710, Cortex-A715, Cortex-A72, Cortex-A7…...
企业电子招标采购系统源码java 版本 Spring Cloud + Spring Boot
项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及…...
7.Mysql 事务底层
一、事务的基础知识 mysql中的事务 分为 显式事务 和 隐式事务。 1.1 显式事务 显式事务就是我们手动开启事务,并且提交事务比如: -- 开启事务 begin; -- 执行查询语句 select *from where id = 1 for update ; -- 提交事务 commit;1.2 隐式事务 在 MySQL 中,隐式事务是…...
15.DIY可视化-拖拽设计1天搞定主流小程序-分类联动文章列表实时刷新
分类联动文章列表实时刷新 本教程均在第一节中项目启动下操作 分类联动文章列表实时刷新前言需求一:功能实现:点击首页分类,对应分类内容显示到当前页一、清空原分类界面:二. 设置选项卡三:设定展示内容字段:1.跨页面复制:文章分类组件到分类
CRect rect; this->GetClientRect(rect); pDC->Ellipse(rect); // DDALineView.cpp : implementation of the CDDALineView class // #include “stdafx.h” #include “DDALine.h” #include “DDALineDoc.h” #include “DDALineView.h” #ifdef _DEBUG #define new…...
Spark大数据处理学习笔记(3.2.1)掌握RDD算子
该文章主要为完成实训任务,详细实现过程及结果见【http://t.csdn.cn/FArNP】 文章目录 一、准备工作1.1 准备文件1. 准备本地系统文件2. 把文件上传到 1.2 启动Spark Shell1. 启动HDFS服务2. 启动Spark服务3. 启动Spark Shell 二、掌握转换算子2.1 映射算子 - map()…...
lammps初级:石墨烯、金属材料、纳米流体、热传导、多成分体系、金属、半导体材料的辐照、自建分子力场、MOFS、H2/CO2混合气体等模拟
1 LAMMPS的基础入门——初识LAMMPS是什么?能干什么?怎么用? 1.1 LAMMPS在win10和ubuntu系统的安装及使用 1.2 in文件结构格式 1.3 in文件基本语法:结合实例,讲解in文件常用命令 1.4 data文件格式 1.5 LAMMPS常见错误解…...
【MarkerDown】CSDN Markdown之时序图sequenceDiagram详解
CSDN Markdown之时序图sequenceDiagram详解 序列图 sequenceDiagram参与者与组参与者 participant拟人符号 actor别名 as组 box 消息(连线)激活/失活 activate/deactivate备注 Note循环 loop备选 Alt并行 par临界区 critical中断 break背景高亮 rect注释 %%转义字符的实体代码序…...
ReentrantLock实现原理-公平锁
在ReentrantLock实现原理(1)一节中,我们了解了ReentrantLock非公平锁的获取流程,在本节中我们来看下ReentrantLock公平锁的创建以及锁管理流程 创建ReentrantLock公平锁 创建公平锁代码如下: ReentrantLock reentrantLock new ReentrantL…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
