Devo rimuovere console.log dal codice di produzione?


88

Al momento ho questa dichiarazione JS ovunque nel mio codice:

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

Mi chiedo se ciò sia costoso o abbia effetti collaterali negativi nella produzione.

Sono libero di lasciare il login lato client o dovrebbe andare?

EDIT: Alla fine, suppongo che il miglior argomento che io (e qualcun altro?) Possa venire in mente è che c'è una quantità possibilmente non trascurabile di dati extra trasferiti tra il server e il client lasciando i messaggi di registrazione lasciati. Se il codice di produzione deve essere completamente ottimizzato, il logging dovrà essere rimosso per ridurre le dimensioni del javascript inviato al client.


Risposte:


41

Si dovrebbe non aggiungere strumenti di sviluppo per la produzione di una pagina.

Per rispondere all'altra domanda: il codice non può avere un effetto collaterale negativo:

  • window.consolerestituirà false se consolenon è definito
  • console.log("Foo")stamperà il messaggio alla console quando è definito (a condizione che la pagina non venga sovrascritta console.logda una non funzione).

43
Sono d'accordo con te in linea di principio. Ma penso che saremmo tutti d'accordo sul fatto che l'implementazione della registrazione che non si attiva tranne durante la modalità di debug è necessaria per un codice lato server di qualità. Nessuno passa e rimuove la registrazione per una versione di produzione: il programma determina il livello di registrazione necessario e reagisce di conseguenza. Spero che ci sia qualcosa di simile a questo per la programmazione lato client ... anche semplicemente impostando una variabile "isDebug", se necessario. Perché dovrei voler caricare il prossimo sviluppatore rendendo necessario tornare indietro e aggiungere nuovamente la registrazione per le aree problematiche in futuro?
Sean Anderson

11
Squallido come? Direi che dire che la console per sviluppatori fa parte del sito Web di produzione è come dire che i file di registro fanno parte di un'applicazione. Sì, sono entrambi generati dal codice, ma dovrebbe esserci un certo livello di comprensione che i log devono essere lasciati da qualche parte. Tuttavia, se le dichiarazioni all'interno dei log siano user-friendly o meno è un'altra questione.
Sean Anderson

4
Come si elimina automaticamente il codice di debug prima di ridurre a icona? Esistono molti moduli che possono assumere un messaggio di registro lato client.
Sean Anderson

6
È possibile contrassegnare ogni pezzo di codice di debug, ad esempio anteponendo / postfissando una riga di codice di debug con un commento. Esempio: /*DEBUG:start*/console.log("Foo");/*DEBUG:end*/. Quindi, utilizza una RegExp per rimuovere tutte le occorrenze di /*DENUG-start*/[\S\s]*?/*DEBUG-end*/. I restanti caratteri di spazio vuoto verranno rimossi dal minimizer.
Rob W

3
A meno che questa risposta non dica PERCHÉ non dovresti farlo, non è davvero utile. Dovremmo solo accettare ciecamente che è brutto senza prove o ragioni?
ESR

48

Un altro modo per risolvere questo problema è 'stub' l'oggetto console quando non è definito in modo che non vengano generati errori in contesti che non hanno la console, ad es.

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

hai capito ... ci sono molte funzioni definite sulle varie implementazioni della console, quindi potresti stub tutte o solo quelle che usi (es. se usi console.loge non usi mai console.profile, console.timeecc ...)

Questa per me è un'alternativa migliore nello sviluppo rispetto all'aggiunta di condizionali prima di ogni chiamata o al non utilizzo.

vedi anche: È una cattiva idea lasciare le chiamate "console.log ()" nel tuo prodotto sul codice JavaScript?


6
Buona idea. Sono necessarie solo alcune correzioni. Il debugger JS di Visual Studio lancia al primo console.log = noOp () perché l'oggetto console stesso non è definito. L'ho fatto in questo modo: console = {log: noOp, warn: noOp, error: noOp}. Nota anche che non vuoi mettere () dopo noOp - vuoi assegnare la funzione stessa e non il suo valore di ritorno. Testato su debugger JS di Visual Studio e IE9 - ora funziona bene.
JustAMartin

3
Cordiali saluti, se si sta già utilizzando jQuery, che forniscono una funzione noop: $.noop.
schiacciare il

28

UglifyJS2

Se stai usando questo minifier, puoi impostare l' drop_consoleopzione :

Passa true per scartare le chiamate alle funzioni console. *

Quindi suggerirei di lasciare le console.logchiamate così come sono per la parte più complicata della base di codice.


3
Se stai usando grunt e uglify , è disponibile anche la stessa opzione (sembra che uglify sia basato su UglifyJS2): github.com/gruntjs/…
Inclina il

1
La domanda è "dovrei", non "come faccio".
ESR

Dovresti lasciare console.errors in. Se qualcuno in produzione ha un problema, puoi facilmente diagnosticare. Non eliminare console.errors!
Oliver Watkins

Se ci sarà bisogno di loro allora si può solo impostare drop_consolea false, osservarli e nasconderli di nuovo.
terales

16

Se la minificazione fa parte del processo di creazione, è possibile utilizzarla per eliminare il codice di debug, come spiegato qui con il compilatore di chiusura di Google: Escludi il codice JavaScript di debug durante la minificazione

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

Se compili con ottimizzazioni avanzate, questo codice verrà persino identificato come morto e rimosso completamente


1
Grazie! Stavo cercando questo. :)
Sean Anderson

5

Sì. console.log genererà un'eccezione nei browser che non lo supportano (l'oggetto console non verrà trovato).


non con la sua valutazione di cortocircuito, purché la finestra sia definita
Joe

1
Sebbene mi sia sfuggito nella mia risposta iniziale, dovresti anche controllare console.log.
MK_Dev

Per lo più faccio solo window.console per evitare problemi con IE. Devo ancora incappare in una situazione in cui il registro è stato ignorato involontariamente, ma sono sicuro che potrebbe accadere.
Sean Anderson

@MK_Dev Vale a dire, quali browser?
goodpixels

È il 2019. Dubito che ci siano browser che non supportano la console.
Oliver Watkins

5

In genere sì, non è una buona idea esporre i messaggi di log nel codice di produzione.

Idealmente, dovresti rimuovere tali messaggi di log con uno script di build prima della distribuzione; ma molte (la maggior parte) persone non usano un processo di compilazione (me compreso).

Ecco un breve frammento di codice che ho utilizzato ultimamente per risolvere questo dilemma. Corregge gli errori causati da un non definito consolenel vecchio IE, oltre a disabilitare la registrazione se in "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);
}

Sono abbastanza sicuro di aver preso gran parte di quanto sopra addConsoleNoOpf'n da un'altra risposta su SO, ma non riesco a trovarlo in questo momento. Aggiungerò un riferimento più tardi se lo trovo.

modifica: non il post a cui stavo pensando, ma ecco un approccio simile: https://github.com/paulmillr/console-polyfill/blob/master/index.js


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

Utilizzo:

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

1

Sì, è buona norma utilizzarlo console.logper scopi di debug javascript, ma deve essere rimosso dal server di produzione o se necessario può essere aggiunto sul server di produzione con alcuni punti chiave da prendere in considerazione:

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

Il blocco di codice sopra deve essere utilizzato ovunque per la registrazione al fine di verificare prima se la console è supportata per il browser corrente e se il debug è abilitato o meno.

isDebugEnabled deve essere impostato come vero o falso in base al nostro ambiente.


1

TL; DR

Idea: la registrazione degli oggetti impedisce che vengano raccolti dalla spazzatura.

Dettagli

  1. Se passi oggetti a console.log questi oggetti sono accessibili per riferimento dalla console di DevTools. Puoi controllarlo registrando l'oggetto, modificandolo e scoprendo che i vecchi messaggi riflettono le modifiche successive dell'oggetto.
  2. Se i registri sono troppo lunghi, i vecchi messaggi vengono eliminati in Chrome.
  3. Se i registri sono brevi, i vecchi messaggi non vengono rimossi, se questi messaggi fanno riferimento a oggetti, questi oggetti non sono Garbage Collected.

È solo un'idea: ho controllato i punti 1 e 2 ma non 3.

Soluzione

Se desideri conservare i registri per motivi di risoluzione dei problemi lato client o altre esigenze, allora:

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

0

Fondamentalmente sovrascrivo la funzione console.log con quella che ha conoscenza di dove viene eseguito il codice. Così posso continuare a usare console.log come faccio sempre. Sa automaticamente che sono in modalità dev / qa o in produzione. C'è anche un modo per forzarlo. Ecco un violino funzionante. http://jsfiddle.net/bsurela/Zneek/

Ecco lo snippet mentre lo stack overflow viene suggerito dalle persone che pubblicano 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);
    }
},

0

So che questa è una domanda piuttosto vecchia e non ha avuto molta attività da un po '. Volevo solo aggiungere la mia soluzione che ho trovato e che sembra funzionare abbastanza bene per 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;
            }
        }
    }

Quindi di solito creo una funzione nei miei script come questa o potresti renderla disponibile in uno script globale:

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 poi lo uso al posto di console.log in questo modo:

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

0

Se il flusso di lavoro viene eseguito utilizzando gli strumenti giusti come parcel/ webpack, non è più un mal di testa, perché con la productionbuild console.logviene abbandonato. Anche pochi anni prima con Gulp/ Gruntavrebbe potuto essere automatizzato.

Molti dei quadri moderni come Angular, React, Svelte, Vue.jsvengono con che configurazione out-of-the-box. Fondamentalmente, non devi fare nulla, purché distribuisca la build corretta, cioè productionuna, developmentche non avrà ancora console.log.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.