我应该从生产代码中删除console.log吗?

时间:2011-11-03 21:28:45

标签: javascript logging

我目前在我的代码中到处都有这个JS语句:

window.console && console.log("Foo");

我想知道这是否代价高昂,或者在生产中是否有任何负面影响。

我可以自由离开客户端登录,还是应该离开?

编辑:最后,我认为我(以及其他任何人?)能够提出的最好的论点是,通过留下记录消息,在服务器和客户端之间传输的额外数据可能是不可忽略的。如果要完全优化生产代码,则必须删除日志记录以减少发送给客户端的javascript的大小。

13 个答案:

答案 0 :(得分:47)

另一种解决这个问题的方法是在未定义控制台对象时将其“存根”出来,这样在没有控制台的情境中就不会抛出任何错误,即

if (!window.console) {
  var noOp = function(){}; // no-op function
  console = {
    log: noOp,
    warn: noOp,
    error: noOp
  }
}

你明白了...在控制台的各种实现上定义了很多函数,所以你可以将它们全部或仅使用你所使用的函数(例如,如果你只使用console.log和从未使用console.profileconsole.time等...)

这对我来说是一个更好的选择,而不是在每次通话前添加条件,或者不使用它们。

另见:Is it a bad idea to leave "console.log()" calls in your producton JavaScript code?

答案 1 :(得分:33)

您应该将开发工具添加到生产页面。

回答另一个问题:代码不能产生负面影响:

    如果window.console未定义,
  • console将评估为false
  • console.log("Foo")会在定义时将消息打印到控制台(前提是该页面不会被非功能覆盖console.log)。

答案 2 :(得分:27)

UglifyJS2

如果您使用此缩小器,则可以设置drop_console option

  

传递true以放弃对console。*函数的调用

所以我建议保留console.log次调用,因为它们是代码库中最棘手的部分。

答案 3 :(得分:16)

如果缩小是构建过程的一部分,您可以使用它去除调试代码,如此处使用Google闭包编译器所述:Exclude debug JavaScript code during minification

if (DEBUG) {
  console.log("Won't be logged if compiled with --define='DEBUG=false'")
}

如果使用高级优化进行编译,则此代码甚至会被识别为已死并完全删除

答案 4 :(得分:5)

是。 console.log将在不支持它的浏览器中抛出异常(将找不到控制台对象)。

答案 5 :(得分:4)

通常是的,在生产代码中公开日志消息并不是一个好主意。

理想情况下,您应该在部署之前使用构建脚本删除此类日志消息;但是很多(大多数)人不使用构建过程(包括我)。

这是我最近一直用来解决这个难题的一些代码的简短摘要。它修复了旧IE中由未定义的console引起的错误,以及在“development_mode”中禁用日志记录。

// fn to add blank (noOp) function for all console methods
var addConsoleNoOp =  function (window) {
    var names = ["log", "debug", "info", "warn", "error",
        "assert", "dir", "dirxml", "group", "groupEnd", "time",
        "timeEnd", "count", "trace", "profile", "profileEnd"],
        i, l = names.length,
        noOp = function () {};
    window.console = {};
    for (i = 0; i < l; i = i + 1) {
        window.console[names[i]] = noOp;
    }
};

// call addConsoleNoOp() if console is undefined or if in production
if (!window.console || !window.development_mode) {
    this.addConsoleNoOp(window);
}

我很确定我从SO上的另一个答案中取了上述addConsoleNoOp f'n的大部分内容,但现在找不到。如果我找到它,我会稍后添加一个参考。

编辑:不是我想到的帖子,但这是一个类似的方法:https://github.com/paulmillr/console-polyfill/blob/master/index.js

答案 6 :(得分:2)

var AppLogger = (function () {
  var debug = false;
  var AppLogger = function (isDebug) {
    debug = isDebug;
  }
  AppLogger.conlog = function (data) {
    if (window.console && debug) {
        console.log(data);
    }
  }
  AppLogger.prototype = {
    conlog: function (data) {
        if (window.console && debug) {
            console.log(data);
        }
    }
  };
return AppLogger;
})();

<强> 用法:

var debugMode=true;
var appLogger = new AppLogger(debugMode);
appLogger.conlog('test');

答案 7 :(得分:1)

是的,使用console.log进行javascript调试的良好做法,但需要从生产服务器中删除它,或者如果需要可以在生产服务器上添加一些关键点考虑:

**var isDebugEnabled="Get boolean value from Configuration file to check whether debug is enabled or not".**
if (window.console && isDebugEnabled) {
    console.log("Debug Message");
}

以上代码块必须在任何地方用于记录,以便首先验证当前浏览器是否支持控制台以及是否启用了调试。

  

isDebugEnabled必须根据我们的设置为真或假   环境。

答案 8 :(得分:1)

TL; DR

想法:记录对象阻止它们被垃圾收集。

详细

  1. 如果将对象传递给console.log,则可以通过DevTools控制台的引用访问这些对象。您可以通过记录对象,对其进行变更以及发现旧消息反映对象的后续更改来检查它。
  2. 如果日志过长,旧的邮件会在Chrome中被删除。
  3. 如果日志很短,则不会删除旧邮件,如果这些邮件引用对象,则这些对象不是垃圾收集。
  4. 这只是一个想法:我检查了第1点和第2点,但没有检查3点。

    解决方案

    如果您想为了客户端故障排除或其他需要而保留日志,那么:

    ['log', 'warn', 'error'].forEach( (meth) => {
      const _meth = window.console[meth].bind(console);
      window.console[meth] = function(...args) { _meth(...args.map((arg) => '' + arg)) }
    });
    

答案 9 :(得分:0)

我基本上用一个知道运行代码的地方覆盖console.log函数。因此,我可以像往常一样继续使用console.log。它会自动知道我处于dev / qa模式或生产中。还有一种强迫它的方法。 这是一个工作小提琴。 http://jsfiddle.net/bsurela/Zneek/

这是一个片段,因为发布jsfiddle

的人会暗示堆栈溢出
  log:function(obj)
{
    if(window.location.hostname === domainName)
    {
        if(window.myLogger.force === true)
        {
            window.myLogger.original.apply(this,arguments);
        }
    }else {
        window.myLogger.original.apply(this,arguments);
    }
},

答案 10 :(得分:0)

我知道这是一个很老的问题,而且一段时间内没有太多活动。我只是想添加自己想出的解决方案,对我来说似乎很好用。

CryptAcquireCertificatePrivateKey

然后我通常会在这样的脚本中创建一个函数,或者您可以在全局脚本中使它可用:

    /**
     * Logger For Console Logging 
     */
    Global.loggingEnabled = true;
    Global.logMode = 'all';
    Global.log = (mode, string) => {    
        if(Global.loggingEnabled){
            switch(mode){
              case 'debug':
                  if(Global.logMode == 'debug' || Global.logMode == 'all'){
                    console.log('Debug: '+JSON.stringify(string));
                  }
                  break;
              case 'error':
                  if(Global.logMode == 'error' || Global.logMode == 'all'){
                    console.log('Error: '+JSON.stringify(string));
                  }       
                  break;
              case 'info':
                  if(Global.logMode == 'info' || Global.logMode == 'all'){
                    console.log('Info: '+JSON.stringify(string));
                  }
                  break;
            }
        }
    }

然后我就这样使用它而不是console.log:

Something.fail = (message_string, data, error_type, function_name, line_number) => {
    try{

        if(error_type == undefined){
            error_type = 'error';
        }

        Global.showErrorMessage(message_string, true);
        Global.spinner(100, false);

        Global.log(error_type, function_name);
        Global.log(error_type, 'Line: '+line_number);
        Global.log(error_type, 'Error: '+data);

    }catch(error){
        if(is_global){
            Global.spinner(100, false);
            Global.log('error', 'Error: '+error);
            Global.log('error', 'Undefined Error...');
        }else{
            console.log('Error:'+error);
            console.log('Global Not Loaded!');
        }           
    }   
}

答案 11 :(得分:0)

如果使用正确的工具(例如parcel / webpack完成工作流,则不再麻烦,因为使用production构建console.log被丢弃。甚至早在几年前,Gulp / Grunt就可以实现自动化。

许多现代框架,例如AngularReactSvelteVue.js都是现成的设置。基本上,只要部署正确的构建即可,您无需执行任何操作,即production而不是development仍将具有console.log的构建。

答案 12 :(得分:0)

不要把事情复杂化!我个人在开发过程中一直都在使用 console.log,这样可以节省时间。对于生产,我只添加一行代码(在我的例子中的“生产配置文件”中)禁用所有日志:

window.console.log = () => {};

完成;) 这个猴子修补 window.console 并用空函数替换 log 函数,禁用输出。

在大多数情况下,这对我来说已经足够了。如果您想“一路”并从代码中删除 console.logs 以减小包大小,则必须更改 js 的捆绑方式(例如,使用 minifier 或其他内容删除 console.logs)

此外,我认为您实际上可以强调将它们留在其中 - 即使在生产中也是如此。它对普通用户没有任何改变,但可以真正加快理解奇怪的“异国浏览器”问题。它不像可能包含关键信息的后端日志。无论如何,这一切都在前端,不显示日志消息,因为您害怕透露用户不应该知道的内容实际上只是“默默无闻的安全性”,并且应该让您思考为什么这些信息甚至在前端可用地方。只是我的意见。