¿Debería eliminar console.log del código de producción?

86

Actualmente tengo esta declaración JS en todas partes en mi código:

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

Me pregunto si esto es costoso o tiene efectos secundarios negativos en la producción.

¿Soy libre de dejar el inicio de sesión del lado del cliente, o debería hacerlo?

EDITAR: Al final, supongo que el mejor argumento que se me ocurre (¿y alguien más?) Es que hay una cantidad posiblemente no despreciable de datos adicionales transferidos entre el servidor y el cliente al dejar mensajes de registro. Si El código de producción se optimizará por completo, será necesario eliminar el registro para reducir el tamaño de JavaScript que se envía al cliente.

Sean Anderson
fuente

Respuestas:

41

Usted debe no añadir herramientas de desarrollo para la producción de una página.

Para responder a la otra pregunta: el código no puede tener un efecto secundario negativo:

  • window.consoleevaluará como falso si consoleno está definido
  • console.log("Foo")imprimirá el mensaje en la consola cuando esté definido (siempre que la página no se sobrescriba console.logcon una no función).
Rob W
fuente
43
Estoy de acuerdo contigo en principio. Pero creo que todos estaríamos de acuerdo en que la implementación del registro que no se activa excepto durante el modo de depuración es necesaria para obtener un código de calidad del lado del servidor. Nadie revisa y elimina su registro para una versión de producción: el programa determina qué nivel de registro es necesario y reacciona en consecuencia. Espero que haya algo parecido a esto para la programación del lado del cliente ... incluso simplemente estableciendo una variable "isDebug", si es necesario. ¿Por qué querría molestar al próximo desarrollador al tener que volver atrás y volver a agregar el registro para áreas problemáticas en el futuro?
Sean Anderson
11
Shabby cómo? Yo diría que decir que la consola del desarrollador es parte del sitio web de producción es como decir que los archivos de registro son parte de una aplicación. Sí, ambos son generados por código, pero debería haber cierto nivel de comprensión de que los registros deben dejarse en algún lugar. Sin embargo, si las declaraciones dentro de los registros son fáciles de usar o no, es otro asunto.
Sean Anderson
4
¿Cómo eliminaría automáticamente el código de depuración antes de minimizarlo? Hay una gran cantidad de formas que puede tomar un mensaje de registro del lado del cliente.
Sean Anderson
6
Puede marcar cada fragmento de código de depuración, por ejemplo, añadiendo un prefijo / postfijo a una línea de código de depuración con un comentario. Ejemplo: /*DEBUG:start*/console.log("Foo");/*DEBUG:end*/. Luego, use una expresión regular para eliminar todas las apariciones de /*DENUG-start*/[\S\s]*?/*DEBUG-end*/. El minimizador eliminará los caracteres de espacio en blanco restantes.
Rob W
3
A menos que esta respuesta diga POR QUÉ no debería hacerlo, realmente no es útil. ¿Se supone que debemos aceptar ciegamente que es malo sin pruebas ni razones?
ESR
48

Otra forma de lidiar con esto es 'eliminar' el objeto de la consola cuando no está definido para que no se produzcan errores en contextos que no tienen la consola, es decir

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

entiendes la idea ... hay muchas funciones definidas en las diversas implementaciones de la consola, por lo que podrías eliminarlas todas o solo las que usas (por ejemplo, si solo usas console.logy nunca usas console.profile, console.timeetc.)

Para mí, esta es una mejor alternativa en desarrollo que agregar condicionales al frente de cada llamada o no usarlos.

vea también: ¿Es una mala idea dejar las llamadas "console.log ()" en su producto en el código JavaScript?

craigb
fuente
6
Buena idea. Solo se necesitan algunas correcciones. El depurador de Visual Studio JS arroja la primera consola.log = noOp () porque el objeto de la consola en sí no está definido. Lo hice así: console = {log: noOp, warn: noOp, error: noOp}. También observe que no quiere poner () después de noOp - quiere asignar la función en sí y no su valor de retorno. Probado en el depurador Visual Studio JS e IE9; ahora funciona bien.
JustAMartin
3
Para su información, si ya está usando jQuery, que proporcionan una función NOOP: $.noop.
Crush el
28

UglifyJS2

Si está utilizando este minificador, puede configurar la drop_consoleopción :

Pase true para descartar llamadas a la consola. * Funciones

Por lo tanto, sugeriría dejar las console.logllamadas como están para la parte más complicada del código base.

terales
fuente
3
Si está usando grunt y uglify , la misma opción también está disponible (parece que uglify se basa en UglifyJS2): github.com/gruntjs/…
Tilt
1
La pregunta es "debería", no "cómo lo hago".
ESR
Debe dejar console.errors en. Si alguien en producción tiene un problema, puede diagnosticarlo fácilmente. ¡No elimine los errores de consola!
Oliver Watkins
Si va a haber una necesidad de ellos a continuación, puedes configurar drop_consolea false, observarlos y esconderlos de nuevo.
terales
16

Si la minificación es parte de su proceso de compilación, puede usarla para eliminar el código de depuración, como se explica aquí con el compilador de cierre de Google: Excluya el código JavaScript de depuración durante la minificación

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

Si compila con optimizaciones avanzadas, este código incluso se identificará como muerto y se eliminará por completo

wutz
fuente
1
¡Gracias! Yo estaba buscando esto. :)
Sean Anderson
5

Si. console.log lanzará una excepción en los navegadores que no lo admiten (no se encontrará el objeto de la consola).

MK_Dev
fuente
no con su evaluación de cortocircuito, siempre que la ventana esté definida
Joe
1
Aunque me lo perdí en mi respuesta inicial, también se debe verificar el archivo console.log.
MK_Dev
La mayoría de las veces solo hago window.console para evitar problemas con IE. Todavía tengo que encontrarme con una situación en la que el registro se haya anulado sin querer, pero estoy seguro de que podría suceder.
Sean Anderson
@MK_Dev Es decir, ¿qué navegadores?
goodpixels
Es 2019. Dudo que haya navegadores que no sean compatibles con la consola.
Oliver Watkins
5

Generalmente sí, no es una buena idea exponer mensajes de registro en su código de producción.

Idealmente, debería eliminar dichos mensajes de registro con un script de compilación antes de la implementación; pero mucha (la mayoría) de la gente no usa un proceso de construcción (incluyéndome a mí).

Aquí hay un pequeño fragmento de código que he estado usando últimamente para resolver este dilema. Corrige errores causados ​​por un indefinido consoleen el IE antiguo, así como deshabilita el registro si está en "modo_desarrollo".

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

Estoy bastante seguro de que tomé gran parte del addConsoleNoOpf'n anterior de otra respuesta en SO, pero no puedo encontrarlo en este momento. Agregaré una referencia más tarde si la encuentro.

editar: No es la publicación en la que estaba pensando, pero aquí hay un enfoque similar: https://github.com/paulmillr/console-polyfill/blob/master/index.js

Zach Lysobey
fuente
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
fuente
1

Sí, es una buena práctica usarlo console.logpara fines de depuración de JavaScript, pero debe eliminarse del servidor de producción o, si es necesario, puede agregarse en el servidor de producción con algunos puntos clave que deben tenerse en cuenta:

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

El bloque de código anterior debe usarse en todas partes para iniciar sesión con el fin de verificar primero si la consola es compatible con el navegador actual y si la depuración está habilitada o no.

isDebugEnabled tiene que establecerse como verdadero o falso según nuestro entorno.

shanky
fuente
1

TL; DR

Idea: Registrar objetos impide que sean recolectados como basura.

Detalles

  1. Si pasa objetos a, console.logentonces estos objetos son accesibles por referencia desde la consola de DevTools. Puede comprobarlo registrando el objeto, modificándolo y descubriendo que los mensajes antiguos reflejan cambios posteriores del objeto.
  2. Si los registros son demasiado largos, los mensajes antiguos se eliminan en Chrome.
  3. Si los registros son cortos, los mensajes antiguos no se eliminan; si estos mensajes hacen referencia a objetos, estos objetos no se recolectan como basura.

Es solo una idea: verifiqué los puntos 1 y 2, pero no el 3.

Solución

Si desea mantener registros para solucionar problemas del lado del cliente u otras necesidades, entonces:

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

Básicamente, sobrescribo la función console.log con la que tiene conocimiento de dónde se está ejecutando el código. Por lo tanto, puedo seguir usando console.log como siempre. Automáticamente sabe que estoy en modo dev / qa o en producción. También hay una forma de forzarlo. Aquí hay un violín que funciona. http://jsfiddle.net/bsurela/Zneek/

Aquí está el fragmento, ya que las personas que publican jsfiddle insinúan el desbordamiento de pila

  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
fuente
0

Sé que esta es una pregunta bastante antigua y no ha tenido mucha actividad en un tiempo. Solo quería agregar la solución que se me ocurrió y que parece funcionar bastante bien para mí.

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

Luego, normalmente creo una función en mis scripts como este o puede hacerla disponible en un 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!');
        }           
    }   
}

Y luego solo uso eso en lugar de console.log así:

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
fuente
0

Si el flujo de trabajo se realiza con las herramientas adecuadas, como parcel/, webpackentonces ya no es un dolor de cabeza, porque con la productioncompilación console.logse está abandonando. Incluso unos años antes con Gulp/ Gruntpodría haberse automatizado también.

Muchos de los marcos modernos, tales como Angular, React, Svelte, Vue.jsvienen con que la instalación fuera de la caja. Básicamente, no tiene que hacer nada, siempre y cuando implemente la compilación correcta, es decir production, una, no la developmentque aún tendrá console.log.

Daniel Danielecki
fuente