简体   繁体   English

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

[英]Should I be removing console.log from production code?

I currently have this JS statement everywhere in my code:我目前在我的代码中到处都有这个 JS 语句:

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

I am wondering if this is costly at all, or has any negative side-effects in production.我想知道这是否成本高昂,或者对生产有任何负面影响。

Am I free to leave client-side logging in, or should it go?我可以自由地离开客户端登录,还是应该离开?

EDIT: In the end, I suppose the best argument I (and anyone else?) can come up with is that there is a possibly non-negligible amount of extra data transferred between the server and the client by leaving logging messages left in. If production code is to be fully optimized, logging will have to be removed to reduce the size of javascript being sent to the client.编辑:最后,我想我(和其他任何人?)能提出的最佳论点是,通过保留日志消息,在服务器和客户端之间传输的额外数据量可能不可忽略。如果生产代码要完全优化,必须删除日志记录以减少发送到客户端的 javascript 的大小。

Another way of dealing with this is to 'stub' out the console object when it isn't defined so no errors are thrown in contexts that do not have the console ie解决此问题的另一种方法是在控制台对象未定义时将其“存根”,以便在没有控制台的上下文中不会抛出错误,即

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

you get the idea... there are a lot of functions defined on the various implementations of the console, so you could stub them all or just the ones you use (eg if you only ever use console.log and never used console.profile , console.time etc...)你明白了……在控制台的各种实现上定义了很多函数,所以你可以存根它们全部或只是你使用的那些(例如,如果你只使用过console.log而从未使用过console.profile , console.time等...)

This for me is a better alternative in development than adding conditionals in front of every call, or not using them.对我来说,这比在每次调用前添加条件或不使用它们更好的选择。

see also: Is it a bad idea to leave "console.log()" calls in your producton JavaScript code?另请参阅: 在您的产品中保留 JavaScript 代码中的“console.log()”调用是否是一个坏主意?

You should not add development tools to a production page.应该开发工具添加到生产页面。

To answer the other question: The code cannot have a negative side-effect:回答另一个问题:代码不能有负面影响:

  • window.console will evaluate to false if console is not defined如果console未定义, window.console将评估为 false
  • console.log("Foo") will print the message to the console when it's defined (provided that the page does not overwrite console.log by a non-function). console.log("Foo")将在定义时将消息打印到控制台(前提是页面不会通过非函数覆盖console.log )。

UglifyJS2丑化JS2

If you are using this minifier, you can set drop_console option :如果你正在使用这个压缩器,你可以设置drop_console选项

Pass true to discard calls to console.* functions传递 true 以放弃对 console.* 函数的调用

So I would suggest to leave console.log calls as they are for a most trickiest part of the codebase.所以我建议保留console.log调用,因为它们是代码库中最棘手的部分。

If minification is part of your build process, you may use it to strip out debug code, as explained here with Google closure compiler: Exclude debug JavaScript code during minification如果缩小是您构建过程的一部分,您可以使用它来去除调试代码,如谷歌闭包编译器所解释的: 在缩小期间排除调试 JavaScript 代码

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

If you compile with advanced optimizations, this code will even be identified as dead and removed entirely如果您使用高级优化进行编译,此代码甚至会被识别为死并完全删除

Generally yes, its not a great idea to expose log messages in your production code.通常是的,在生产代码中公开日志消息不是一个好主意。

Ideally, you should remove such log messages with a build script before deployment;理想情况下,您应该在部署之前使用构建脚本删除此类日志消息; but many (most) people do not use a build process (including me).但是许多(大多数)人不使用构建过程(包括我)。

Here's a short snippet of some code I've been using lately to solve this dilemma.这是我最近用来解决这个困境的一些代码的一小段。 It fixes errors caused by an undefined console in old IE, as well as disabling logging if in "development_mode".它修复了由旧 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);
}

I'm pretty sure I took much of the above addConsoleNoOp f'n from another answer on SO, but cannot find right now.我很确定我从 SO 的另一个答案中获取了上述addConsoleNoOp f'n 的大部分内容,但现在找不到。 I'll add a reference later if I find it.如果我找到它,我会在以后添加参考。

edit: Not the post I was thinking of, but here's a similar approach: https://github.com/paulmillr/console-polyfill/blob/master/index.js编辑:不是我想到的帖子,但这里有一个类似的方法: https : //github.com/paulmillr/console-polyfill/blob/master/index.js

Yes.是的。 console.log will throw an exception in browsers that don't have support for it (console object will not be found). 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;
})();

Usage:用法:

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

Yes, its good practice to use console.log for javascript debugging purpose, but it needs to be removed from the production server or if needed can be added on production server with some key points to be taken into consideration:是的,将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");
}

Above code block has to be used everywhere for logging in order to first verify whether the console is supported for the current browser and whether debug is enabled or not.为了首先验证当前浏览器是否支持控制台以及是否启用调试,必须在任何地方使用以上代码块进行日志记录。

isDebugEnabled has to be set as true or false based on our environment. isDebugEnabled必须根据我们的环境设置为 true 或 false。

TL;DR TL; 博士

Idea: Logging objects precludes them from being Garbage Collected.想法:记录对象阻止它们被垃圾收集。

Details细节

  1. If you pass objects to console.log then these objects are accessible by reference from console of DevTools.如果您将对象传递给console.log那么这些对象可以通过 DevTools 的控制台引用来访问。 You may check it by logging object, mutating it and finding that old messages reflect later changes of the object.您可以通过记录对象、改变它并发现旧消息反映对象的后续更改来检查它。
  2. If logs are too long old messages do get deleted in Chrome.如果日志太长,旧消息会在 Chrome 中被删除。
  3. If logs are short then old messages are not removed, if these messages reference objects then these objects are not Garbage Collected.如果日志很短,则不会删除旧消息,如果这些消息引用对象,则这些对象不是垃圾收集的。

It's just an idea: I checked points 1 and 2 but not 3.这只是一个想法:我检查了第 1 点和第 2 点,但没有检查第 3 点。

Solution解决方案

If you want to keep logs for sake of client-side troubleshooting or other needs then:如果您想保留日志以用于客户端故障排除或其他需要,则:

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

I basically overwrite the console.log function with the one what has knowledge of where the code is being run.我基本上用知道代码在哪里运行的那个函数覆盖了 console.log 函数。 Thus i can keep using console.log as I do always.因此,我可以像往常一样继续使用 console.log。 It automatically knows that I am in dev/qa mode or in production.它会自动知道我处于 dev/qa 模式还是在生产中。 There is also a way to force it.还有一种方法可以强制它。 Here is a working fiddle.这是一个工作小提琴。 http://jsfiddle.net/bsurela/Zneek/ http://jsfiddle.net/bsurela/Zneek/

Here is the snippet as stack overflow is intimated by people posting jsfiddle这是发布 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);
    }
},

I know this is quite an old question and hasn't had much activity in a while.我知道这是一个很老的问题,并且已经有一段时间没有太多活动了。 I just wanted to add my solution that I came up with which seems to work quite well for me.我只是想添加我想出的解决方案,这似乎对我来说效果很好。

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

Then I typically create a function in my scripts like this or you could make it available in a global script:然后我通常会在我的脚本中像这样创建一个函数,或者您可以在全局脚本中使用它:

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

And then I just use that instead of console.log like this:然后我只是使用它而不是像这样的 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);
}

If the workflow is done using the right tools such as parcel / webpack then it's no longer a headache, because with the production build console.log is being dropped.如果工作流程使用合适的工具,如做parcel / webpack那么它不再头疼,因为随着production建设console.log被丢弃。 Even few years earlier with Gulp / Grunt it could've been automated as well.即使在几年前使用Gulp / Grunt它也可以实现自动化。

Many of the modern frameworks such as Angular , React , Svelte , Vue.js come with that setup out-of-the-box.许多现代框架,如AngularReactSvelteVue.js都带有Vue.js即用的设置。 Basically, you don't have to do anything, as long as you deploy the correct build, ie production one, not development which will still have console.log .基本上,你不必做任何事,只要你部署了正确的构建,即production的,而不是development将仍然console.log

Don't overcomplicate things!不要把事情复杂化! I personally use console.log all the time during development, it's just such a timesaver.我个人在开发过程中一直都在使用 console.log,这样可以节省时间。 For production i just add a single line of code (in the "production profile" in my case) that disable all logs:对于生产,我只添加一行代码(在我的情况下在“生产配置文件”中)禁用所有日志:

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

done ;) This monkey patches window.console and replace the log function with an empty function, disabling the output. done ;) 这个猴子补丁window.console并用空函数替换log函数,禁用输出。

This is good enough for me in most cases.在大多数情况下,这对我来说已经足够了。 If you want to go "all the way" and remove console.logs from your code to decrease bundle size, you have to change the way your js is bundled (eg drop console.logs with minifier or something)如果你想“一路”并从你的代码中删除 console.logs 以减小包的大小,你必须改变你的 js 的捆绑方式(例如使用 minifier 或其他东西删除 console.logs )

Also I think you CAN actually make a strong point for leaving them in - even in production.此外,我认为您实际上可以强调将它们留在 - 即使在生产中。 It doesn't change anything for a normal user but can really speed up understanding weird "exotic-browser" problems.它对普通用户没有任何改变,但可以真正加快理解奇怪的“异国浏览器”问题。 It's not like it's backend-logs that may contain critical information.它不像可能包含关键信息的后端日志。 It's all on the frontend anyway, not showing a log message because you are scared to reveal something a user shouldn't know really is only "security by obscurity" and should make you think why this information is even available on the frontend in the first place.无论如何,这一切都在前端,不显示日志消息,因为您害怕透露用户不应该知道的内容实际上只是“默默无闻的安全性”,并且应该让您思考为什么这些信息甚至在前端可用地方。 Just my opinion.只是我的观点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM