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…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
ZYNQ学习记录FPGA(二)Verilog语言
一、Verilog简介 1.1 HDL(Hardware Description language) 在解释HDL之前,先来了解一下数字系统设计的流程:逻辑设计 -> 电路实现 -> 系统验证。 逻辑设计又称前端,在这个过程中就需要用到HDL,正文…...
无需布线的革命:电力载波技术赋能楼宇自控系统-亚川科技
无需布线的革命:电力载波技术赋能楼宇自控系统 在楼宇自动化领域,传统控制系统依赖复杂的专用通信线路,不仅施工成本高昂,后期维护和扩展也极为不便。电力载波技术(PLC)的突破性应用,彻底改变了…...
深入理解 C++ 左值右值、std::move 与函数重载中的参数传递
在 C 编程中,左值和右值的概念以及std::move的使用,常常让开发者感到困惑。特别是在函数重载场景下,如何合理利用这些特性来优化代码性能、确保语义正确,更是一个值得深入探讨的话题。 在开始之前,先提出几个问题&…...
【Vue】scoped+组件通信+props校验
【scoped作用及原理】 【作用】 默认写在组件中style的样式会全局生效, 因此很容易造成多个组件之间的样式冲突问题 故而可以给组件加上scoped 属性, 令样式只作用于当前组件的标签 作用:防止不同vue组件样式污染 【原理】 给组件加上scoped 属性后…...
