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

Should I be removing console.log from production code?

本文关键字:删除 console log 代码 我应该      更新时间:2023-09-26

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

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

我想知道这是否成本高昂,或者在生产中有任何负面副作用。

我可以离开客户端登录吗?还是应该离开?

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

处理此问题的另一种方法是在未定义控制台对象时"存根"出控制台对象,这样就不会在没有控制台的上下文中抛出错误,即

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

你明白了。。。控制台的各种实现上定义了很多函数,因此您可以将它们全部或仅截取您使用的函数(例如,如果您只使用过console.log,而从未使用过console.profileconsole.time等(

对我来说,这是开发中比在每次调用前添加条件语句或不使用条件语句更好的选择。

另请参阅:离开是个坏主意吗;console.log(("在您的产品中调用JavaScript代码?

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

回答另一个问题:代码不能有负面副作用:

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

UglifyJS2

如果您正在使用此迷你图,您可以设置drop_console选项:

传递true可放弃对控制台的调用。*函数

因此,我建议将console.log调用保留为代码库中最棘手的部分。

如果缩小是构建过程的一部分,您可以使用它来剥离调试代码,如谷歌闭包编译器所述:在缩小期间排除调试JavaScript代码

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

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

Yes。console.log将在不支持它的浏览器中引发异常(找不到控制台对象(。

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

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

下面是我最近用来解决这个难题的一些代码的一小段。它修复了旧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

不要把事情搞得太复杂!在开发过程中,我个人一直在使用console.log,它非常节省时间。对于生产,我只添加了一行代码(在我的"生产配置文件"中(来禁用所有日志:

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

已完成;(此monkey修补window.console,并用空函数替换log函数,从而禁用输出。

在大多数情况下,这对我来说已经足够了。如果你想去";一直";从你的代码中删除console.log以减少捆绑包的大小,你必须改变js的捆绑方式(例如,用minifier之类的东西删除console.logs(

此外,我认为你实际上可以把它们留在生产中。对于普通用户来说,它不会改变任何事情,但确实可以加快理解怪异的";异国情调的浏览器";问题。它不像后端日志可能包含关键信息。你甚至可以通过console.log显示的所有内容显然已经在前端可用了!因为害怕透露安全细节或类似的事情而不显示日志消息实际上只是";"默默无闻的安全";并且应该让你思考为什么这些信息一开始就可以在前端获得!只是我的看法。

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');

是的,使用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必须根据我们的环境

TL;DR

想法:日志记录对象可以防止它们被垃圾回收。

详细信息

  1. 如果您将对象传递给console.log,那么这些对象可以通过DevTools控制台的引用访问。您可以通过记录对象、对其进行更改并发现旧消息反映了对象的后期更改来对其进行检查
  2. 如果日志太长,旧消息确实会在Chrome中被删除
  3. 如果日志很短,则不会删除旧消息,如果这些消息引用对象,则这些对象不会被垃圾回收

这只是一个想法:我检查了第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)) }
});

如果使用正确的工具(如parcel/webpack(来完成工作流,那么它就不再是一个令人头疼的问题,因为随着production的构建,console.log将被删除。即使在几年前,Gulp/Grunt也可以实现自动化。

许多现代框架,如AngularReactSvelteVue.js,都具有开箱即用的设置。基本上,只要部署正确的构建,即production,而不是仍然具有console.logdevelopment,就不必做任何事情。

我基本上用知道代码运行位置的函数覆盖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);
    }
},

我知道这是一个很老的问题,已经有一段时间没有太多活动了。我只是想添加我的解决方案,我提出的似乎对我很有效。

    /**
     * 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;
            }
        }
    }

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

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!');
        }           
    }   
}

然后我就用它代替console.log,如下所示:

try{
 // To Do Somehting
 Something.fail('Debug Something', data, 'debug', 'myFunc()', new Error().lineNumber);
}catch(error){
 Something.fail('Something Failed', error, 'error', 'myFunc()', new Error().lineNumber);
}