怎么满屏的console.log(...)

46 篇文章 0 订阅
46 篇文章 0 订阅

前言


最近接手了一个已经维护了很长时间的后台管理系统,这个项目依旧使用的是 Vue 2。虽然开发上的问题不多,但还是需要做一些本地性的修改和维护。想到这,摸鱼的时间好像又多了几分。
然而,当我打开项目并启动后,发现控制台的打印信息堆积成了一整页。这可不行!不考虑内存泄漏或其他问题,光是调试时,想要在这些杂乱的信息中找到自己的打印内容都十分困难。虽然可以通过在打印时添加特殊符号来区分,但这样做显然很麻烦。


初步想法
恰逢最近看来一些 Webpack 的一些东西(八股文),了解到 loader 和 plugins 的概念。
在 Webpack 中,Loader 是一种转换工具,它的主要功能是对模块的源代码进行转换处理。简而言之,Loader 本质上是一个函数,它接受源代码作为输入,经过处理后返回转换后的代码。Webpack 在处理文件时,会使用 Loader 对文件进行预处理。


相比于 Loader,Plugins 的功能更为强大和灵活。Plugins 是 Webpack 插件系统的一部分,几乎可以用来处理任何构建过程中的操作。Plugins 运行在 Webpack 的整个生命周期阶段,从构建过程的开始到结束,可以对构建过程进行深度的定制和优化。


所有我想是否可以写一个plugins的插件,来自动修改 console.log 语句,使其包含一个特殊的符号。这不仅有助于调试,还能帮助我们在控制台中快速识别出特定的日志信息。


初步实现


定义一个名为log的类,这个类接受一个特殊符号作为参数。正则表达式 reg 用于匹配所有 console.log(...) 语句。Object.keys(compilation.assets) 包含了所有的构建产物文件,使用 forEach 遍历每一个文件并进行修改返回。


在 Plugin 内进行调用时,apply 方法会被 Webpack Compiler 调用,并且在整个编译生命周期都可以访问 Compiler 对象。


class log {
 constructor(icon) {
   this.icon = icon;
 }
 apply(compiler) {
   const _that = this;
   const reg = /(console\.log\([^)]*\))/g;
   compiler.hooks.emit.tap("log", (compilation) => {
     Object.keys(compilation.assets).forEach((item) => {
       let content = compilation.assets[item].source();
       // 确保 content 是字符串
       if (Buffer.isBuffer(content)) {
         content = content.toString();
       }
       content = content.replace(reg, function (match, p1) {
         console.log(match, "!!!!!");
         return match.slice(0, -1) + `,'${_that.icon}')`;
       });

       // 更新构建产物对象
       compilation.assets[item] = {
         source: () => content,
         size: () => content.length,
       };
     });
   });
 }
}
module.exports = log;


我们可以在 plugins 配置中实例化 log 插件,并传入图标参数:


 plugins: [
      new log('🚀🚀🚀') // 在这里实例化 log 插件,并传入图标
    ]

这样就是实现了初步的效果,如下:

这样所有的console.log(...)就会带上你所传入的特殊符号,这样的话其实是没什么太大的用处的,所以下一步需要实现这样的效果

效果进阶


上面的初步实现只是一个简单的效果,但我们还需要考虑一些更复杂的情况。比如,当 console.log 打印多个变量或者是函数时,我们需要进一步处理。


首先,如果 source 是函数类型,则需要执行函数以获取字符串。


// 如果是函数,执行以获取字符串
if (typeof source === "function") {
    source = source();
}


函数的问题解决了的话我们要解决的就是多个变量打印的问题,


if (typeof source === "string") {
 // 使用正则表达式替换源代码中的 console.log() 语句
 source = source.replace(reg, function (match, p1) {
   const args = match.slice(12, -1);
   const newArgs = args
     .split(",")
     .map((item) => {
       return _that.customLog(item);
     })
     .join(",");
   return `console.log(${newArgs},'${_that.icon}')`;
 });
 // 更新构建产物对象
 compilation.assets[item] = {
   source: () => source, // 返回函数
   size: () => source.length,
 };
}

这里,我们对 console.log 内的所有变量进行分割,遍历处理后,再将其组装回 console.log() 内。customLog 的实现如下


customLog(variableValue) {
    if(variableValue.includes("'") || variableValue.includes('"')){
      return  variableValue
    }else{
      let str = variableValue.toString();
      return  `'${str}=',${variableValue}`
    }
  }

这里接受一个到传入来的变量,判断是否是字符串,如果直接打印的字符串的话直接返回就可以了,如果不是的话,那么就进行分割遍历结果就会如下了

结尾


总体代码如下


class log {
  constructor(icon) {
    this.icon = icon;
  }
  apply(compiler) {
    const _that = this;
    // 正则表达console.log()
    const reg = /(console\.log\((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*\))/g;
    compiler.hooks.emit.tap("log", (compilation) => {
      // 遍历所有的构建产物
      Object.keys(compilation.assets).forEach((item) => {
        // 获取当前构建产物的源代码
        let source = compilation.assets[item].source();
        // 如果是函数,执行以获取字符串
        if (typeof source === "function") {
          source = source();
        }
        // 检查source是否是字符串
        if (typeof source === "string") {
          // 使用正则表达式替换源代码中的 console.log() 语句
          source = source.replace(reg, function (match, p1) {
            const args = match.slice(12, -1);
            const newArgs = args
              .split(",")
              .map((item) => {
                return _that.customLog(item);
              })
              .join(",");
            return `console.log(${newArgs},'${_that.icon}')`;
          });
          // 更新构建产物对象
          compilation.assets[item] = {
            source: () => source, // 返回函数
            size: () => source.length,
          };
        } else {
          console.log(source);

          console.error("Error: Compilation asset source is not a string.");
        }
      });
    });
  }
  customLog(variableValue) {
    if (variableValue.includes("'") || variableValue.includes('"')) {
      return variableValue;
    } else {
      let str = variableValue.toString();
      return `'${str}=',${variableValue}`;
    }
  }
}
module.exports = log;


其实这个主要是为了学习如何编写一款插件,因为我也是在学习中,所以很多地方可能会存在问题。有兴趣的可以自己拓展学习一些,例如不对node_model下的进行处理,或者是在正式环境打包的时候删除掉 console.log()。主要是为了熟悉一下plugins的插件

原文链接:https://juejin.cn/post/7405420213469085748

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值