如何优雅的使用console日志

202 阅读4分钟

前言

前几天,我在一个群里被另外一个业务线的同事cue,他丢了一张截图说,你们这些控制台日志能不能做一下优化,不要把埋点这些信息也打印出来,因为他们团队开发的页面使用了我们团队开发的SDK。我觉得确实要优化一下,一是因为在控制台打印太多的日志并不好,特别是一些敏感信息,二是console日志方法在某些场景下会导致内存泄漏,这个就不在这里细讲。于是便回复:马上安排处理!

那我们怎么去处理这些控制台日志呢?其实处理的方式有很多种。

console日志处理方式

1、手动删除console日志

这种可以说是最笨的方法,手动把代码中使用的console的log、error、info等方法删除,看起来是件比较费力的事情,也没啥优势,而且还有一些缺点,一是没法在测试环境去打印一些用来调试或者有其他用途的一些关键日志,如果需要在生产环境定位问题也没法看到任何日志。

2、自定义日志

自定义一个logger,在需要使用日志的地方引入这个logger,在这个logger中增加日志开关,如果是生产环境则默认关闭日志,否则默认打开日志,既然是开关,那必定可以通过某种方式打开或者关闭,实现方式也有很多,例如在url中增加参数用来判断日志是否打开或者关闭,或者在浏览器缓存中,例如local storage中增加变量来判断。这种方式的优点是可以自定义日志的打印方式,例如打印的样式等,另外也可以做到统一管理日志;缺点是需要在使用的文件中每次都引入logger,另外如果项目开发中有同事不知道有自定义的logger或者干脆不遵守项目规范,还是使用的console进行日志的打印,那自定义的logger就没有太大意义,当然这可以用eslint去规避这个问题,禁止在代码中直接使用console。另外,对于历史代码中的console,要手中删除或者修改成自定义的logger。

// 自定义 logger
const logger = {
  isEnabled: false, // 默认关闭日志

  enableLogger: function() {
    this.isEnabled = true;
  },

  disableLogger: function() {
    this.isEnabled = false;
  },
// 以下方法只是简单基于console的方法做了封装,可以根据项目需求自定义,例如增加参数。
  log: function(message) {
    if (this.isEnabled) {
      console.log(message);
    }
  },

  info: function(message) {
    if (this.isEnabled) {
      console.info(message);
    }
  },

  warn: function(message) {
    if (this.isEnabled) {
      console.warn(message);
    }
  },

  error: function(message) {
    if (this.isEnabled) {
      console.error(message);
    }
  }
};

// 检查环境并设置日志状态
function checkEnvironmentAndSetLoggerStatus() {
  const isProduction = process.env.NODE_ENV === 'production';
  const localStorageSettings = JSON.parse(localStorage.getItem('loggerSettings')) || {};

  if (localStorageSettings.openLogger) {
    logger.enableLogger();  
} else if (localStorageSettings.closeLogger) {
    logger.disableLogger(); 
 } else {
    logger.isEnabled = !isProduction; // 默认在开发环境和测试环境打开  }
}

// 检查环境并设置日志状态
checkEnvironmentAndSetLoggerStatus();

// 使用示例:引入logger并调用相关方法
logger.log('This is a log message');
logger.info('This is an info message');
logger.warn('This is a warning message');
logger.error('This is an error message');

3、覆盖console

这种方式是我在项目中用到的方式,就是重写console类及其方法

// console开启关闭
export const consoleSwitch = (function() {
  let oldConsole: any = null; 
 const instance: any = {}; 
 instance.enableConsole = function enableConsole() {  
  if (oldConsole == null) return;  
  window["console"] = oldConsole; 
 }; 
 instance.disableConsole = function disableConsole() { 
   oldConsole = console;  
  const newConsole: any = {};  
  Object.keys(console || {}).forEach(consoleItem => {  
    if (typeof console[consoleItem] === "function") {    
    newConsole[consoleItem] = function() {};   
   }  
  });  
  window["console"] = newConsole; 
 }; 
 return instance;
})();

// 处理不同环境的console日志
export const handleConsole = () => { 
 const env = tools.getHostEnv(); 
 const isPrd = env === "prd"; 
 const closeConsole = localStorage.getItem("closeConsole"); 
 const openConsole = localStorage.getItem("openConsole"); 
 // 除了生产环境外,其他环境默认打开console,在localStorage加closeConsole可以关闭console日志 
if (!isPrd && closeConsole) { 
   consoleSwitch.disableConsole(); 
 }  
// 生产环境默认关闭console日志,在localStorage加openConsole可以打开console日志 
 if (isPrd && !openConsole) {   
     consoleSwitch.disableConsole();
  }};
// 在项目根文件进行引入,处理console日志
handleConsole();

4、使用babel插件处理console日志

使用babel插件也是一种处理方法,毕竟babel的功能太强大了

// webpack.config.js
// 安装babel-plugin-transform-remove-console插件

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = (env, argv) => {
  const isProduction = argv.mode === 'production';

  return {
    entry: './src/index.js',
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'bundle.js'
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env'],
              plugins: isProduction ? ['babel-plugin-transform-remove-console'] : []
            }
          }
        }
      ]
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: './src/index.html'
      })
    ]
  };
};
// .babelrc

{
  "presets": ["@babel/preset-env"],
  "plugins": []
}

总结

so,以上就是一些常见的日志处理方法,如果有其他更好的方式,烦请在评论里补充呢,thanks!