Devo remover o console.log do código de produção?

86

Atualmente, tenho esta instrução JS em todo o meu código:

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

Estou me perguntando se isso é caro ou tem algum efeito colateral negativo na produção.

Estou livre para deixar o login do lado do cliente ou devo sair?

EDIT: No final, suponho que o melhor argumento que eu (e mais alguém?) Posso apresentar é que há uma quantidade possivelmente não desprezível de dados extras transferidos entre o servidor e o cliente, deixando mensagens de registro deixadas. o código de produção deve ser totalmente otimizado, o registro terá que ser removido para reduzir o tamanho do javascript que está sendo enviado ao cliente.

Sean Anderson
fonte

Respostas:

41

Você não deve adicionar ferramentas de desenvolvimento a uma página de produção.

Para responder à outra pergunta: O código não pode ter um efeito colateral negativo:

  • window.consoleserá avaliado como falso se consolenão for definido
  • console.log("Foo")imprimirá a mensagem no console quando for definida (desde que a página não seja substituída console.logpor uma não função).
Rob W
fonte
43
Eu concordo com você em princípio. Mas, acho que todos concordaríamos que a implementação de logs que não disparam, exceto durante o modo de depuração, é necessária para um código de servidor de qualidade. Ninguém passa e remove seu registro para uma versão de produção - o programa determina qual nível de registro é necessário e reage de acordo. Espero que haja algo parecido com isso para programação do lado do cliente ... até mesmo apenas definindo uma variável "isDebug", se necessário. Por que eu iria querer sobrecarregar o próximo desenvolvedor, precisando voltar e adicionar novamente a criação de log para áreas problemáticas no futuro?
Sean Anderson
11
Gasto como? Eu diria que dizer que o console do desenvolvedor é parte do site de produção é como dizer que os arquivos de log são parte de um aplicativo. Sim, ambos são gerados por código, mas deve haver algum nível de entendimento de que os logs devem ser deixados em algum lugar. Se as instruções dentro dos logs são amigáveis ​​ou não, é outra questão.
Sean Anderson
4
Como alguém removeria automaticamente o código de depuração antes de minimizar? Há uma grande quantidade de formas que uma mensagem de log do lado do cliente pode assumir.
Sean Anderson
6
Você pode marcar cada parte do código de depuração, por exemplo, prefixando / postfixando uma linha de código de depuração com um comentário. Exemplo: /*DEBUG:start*/console.log("Foo");/*DEBUG:end*/. Em seguida, use um RegExp para remover todas as ocorrências de /*DENUG-start*/[\S\s]*?/*DEBUG-end*/. Os caracteres de espaço em branco restantes serão removidos pelo minimizador.
Rob W
3
A menos que esta resposta diga POR QUE você não deve fazer isso, não é realmente útil. Devemos apenas aceitar cegamente que é ruim, sem evidências ou razões?
ESR
48

Outra maneira de lidar com isso é 'stub' o objeto de console quando ele não está definido para que nenhum erro seja lançado em contextos que não têm o console, ou seja,

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

você entendeu ... há uma série de funções definidas nas várias implementações do console, então você pode fazer um stub de todas ou apenas aquelas que você usa (por exemplo, se você apenas usa console.loge nunca usa console.profile, console.timeetc ...)

Isso para mim é uma alternativa melhor no desenvolvimento do que adicionar condicionais antes de cada chamada ou não usá-los.

veja também: É uma má ideia deixar chamadas "console.log ()" em seu código JavaScript de produção?

craigb
fonte
6
Boa ideia. Apenas algumas correções necessárias. O depurador do Visual Studio JS lança no primeiro console.log = noOp () porque o próprio objeto do console não está definido. Fiz assim: console = {log: noOp, warn: noOp, error: noOp}. Observe também que você não deseja colocar () após noOp - você deseja atribuir a própria função e não seu valor de retorno. Testado no depurador Visual Studio JS e IE9 - agora funciona bem.
JustAMartin
3
FYI, se você já estiver usando jQuery, eles fornecem uma função noop: $.noop.
esmagamento de
28

UglifyJS2

Se estiver usando este minificador, você pode definir a drop_consoleopção :

Passe verdadeiro para descartar chamadas para funções do console. *

Portanto, sugiro deixar as console.logchamadas como estão para a parte mais complicada da base de código.

terales
fonte
3
Se você estiver usando o grunt e o uglify , a mesma opção também está disponível (parece que o uglify é baseado no UglifyJS2): github.com/gruntjs/…
Tilt
1
A questão é "devo", não "como faço".
ESR
Você deve deixar console.errors em. Se alguém na produção tiver um problema, você poderá diagnosticá-lo facilmente. Não tire console.errors!
Oliver Watkins
Se houver necessidade deles, você pode simplesmente configurá drop_console- falselos, observá-los e ocultá-los novamente.
terales de
16

Se a minificação fizer parte do seu processo de compilação, você pode usá-la para remover o código de depuração, conforme explicado aqui com o compilador de encerramento do Google: Exclua o código JavaScript de depuração durante a minificação

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

Se você compilar com otimizações avançadas, este código será identificado como morto e totalmente removido

wutz
fonte
1
Obrigado! Eu estava procurando por isso. :)
Sean Anderson
5

Sim. console.log lançará uma exceção em navegadores que não têm suporte para ele (o objeto console não será encontrado).

MK_Dev
fonte
não com sua avaliação de curto-circuito, desde que a janela seja definida
Joe
1
Embora eu não tenha percebido na minha resposta inicial, verifique se há console.log também deve ser feita.
MK_Dev
Na maioria das vezes, eu apenas faço o window.console para evitar problemas com o IE. Ainda não me deparei com uma situação em que o log tenha sido cancelado involuntariamente, mas tenho certeza de que isso pode acontecer.
Sean Anderson
@MK_Dev Ou seja, quais navegadores?
goodpixels
É 2019. Duvido que haja algum navegador que não suporte console.
Oliver Watkins
5

Geralmente, sim, não é uma boa ideia expor mensagens de log em seu código de produção.

Idealmente, você deve remover essas mensagens de log com um script de construção antes da implantação; mas muitas (a maioria) pessoas não usam um processo de construção (inclusive eu).

Aqui está um pequeno trecho de código que tenho usado recentemente para resolver esse dilema. Ele corrige erros causados ​​por um indefinido consoleno antigo IE, bem como desabilita o log se estiver em "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);
}

Tenho certeza de que addConsoleNoOpextraí muito das respostas acima de outra resposta no SO, mas não consigo encontrar no momento. Adicionarei uma referência mais tarde, se a encontrar.

editar: Não é a postagem que eu estava pensando, mas aqui está uma abordagem semelhante: https://github.com/paulmillr/console-polyfill/blob/master/index.js

Zach Lysobey
fonte
3
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;
})();

Uso:

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

Sim, é uma boa prática usar console.logpara fins de depuração de javascript, mas precisa ser removido do servidor de produção ou, se necessário, pode ser adicionado no servidor de produção com alguns pontos-chave a serem levados em consideração:

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

O bloco de código acima deve ser usado em todos os lugares para registro, a fim de primeiro verificar se o console é compatível com o navegador atual e se a depuração está habilitada ou não.

isDebugEnabled deve ser definido como verdadeiro ou falso com base em nosso ambiente.

pernilongo
fonte
1

TL; DR

Ideia: Objetos de log impede que sejam Coletados como Lixo.

Detalhes

  1. Se você passar objetos para console.log, esses objetos estarão acessíveis por referência no console do DevTools. Você pode verificá-lo registrando o objeto, alterando-o e descobrindo que as mensagens antigas refletem as alterações posteriores do objeto.
  2. Se os registros forem muito longos, as mensagens antigas serão excluídas do Chrome.
  3. Se os logs forem curtos, as mensagens antigas não serão removidas; se essas mensagens fizerem referência a objetos, esses objetos não serão Coletados como Lixo.

É apenas uma ideia: verifiquei os pontos 1 e 2, mas não 3.

Solução

Se você deseja manter registros para solucionar problemas do lado do cliente ou outras necessidades:

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

Basicamente, sobrescrevo a função console.log por aquela que sabe onde o código está sendo executado. Portanto, posso continuar usando o console.log como sempre. Ele sabe automaticamente que estou no modo dev / qa ou em produção. Também existe uma maneira de forçá-lo. Aqui está um violino funcionando. http://jsfiddle.net/bsurela/Zneek/

Aqui está o snippet como o estouro de pilha é sugerido por pessoas postando 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);
    }
},
Bhavin
fonte
0

Eu sei que esta é uma questão bastante antiga e não teve muita atividade por um tempo. Eu só queria adicionar a minha solução que encontrei e que parece funcionar muito bem para mim.

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

Em seguida, normalmente crio uma função em meus scripts como esta ou você pode disponibilizá-la em um script global:

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

E então eu apenas uso isso em vez de console.log assim:

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);
}
Kyle Coots
fonte
0

Se o fluxo de trabalho é feito usando as ferramentas certas, como parcel/ webpackentão não é mais uma dor de cabeça, porque com o productionbuild console.logestá sendo descartado. Mesmo alguns anos antes, com Gulp/ Gruntpoderia ter sido automatizado também.

Muitas das estruturas modernas, como Angular, React, Svelte, Vue.jsvêm com que a configuração out-of-the-box. Basicamente, você não precisa fazer nada, desde que implemente a compilação correta, ou seja production, uma, developmentque ainda não terá console.log.

Daniel Danielecki
fonte