Sollte ich console.log aus dem Produktionscode entfernen?

84

Ich habe derzeit diese JS-Anweisung überall in meinem Code:

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

Ich frage mich, ob dies überhaupt teuer ist oder negative Nebenwirkungen in der Produktion hat.

Kann ich mich clientseitig anmelden oder sollte es gehen?

BEARBEITEN: Letztendlich denke ich, dass das beste Argument, das ich (und irgendjemand anderes?) Vorbringen kann, ist, dass möglicherweise eine nicht zu vernachlässigende Menge zusätzlicher Daten zwischen dem Server und dem Client übertragen wird, indem Protokollnachrichten hinterlassen werden. Wenn Der Produktionscode muss vollständig optimiert werden. Die Protokollierung muss entfernt werden, um die Größe des an den Client gesendeten Javascript zu verringern.

Sean Anderson
quelle

Antworten:

41

Sie sollten einer Produktionsseite keine Entwicklungstools hinzufügen.

Um die andere Frage zu beantworten: Der Code kann keine negativen Nebenwirkungen haben:

  • window.consolewird als falsch ausgewertet, wenn consolenicht definiert ist
  • console.log("Foo")druckt die Nachricht an die Konsole, wenn sie definiert ist (vorausgesetzt, die Seite wird nicht console.logdurch eine Nichtfunktion überschrieben ).
Rob W.
quelle
43
Ich stimme Ihnen grundsätzlich zu. Ich denke jedoch, wir sind uns alle einig, dass die Implementierung einer Protokollierung, die nur im Debug-Modus ausgelöst wird, für hochwertigen serverseitigen Code erforderlich ist. Niemand geht durch und entfernt die Protokollierung für eine Produktionsversion - das Programm bestimmt, welche Protokollierungsstufe erforderlich ist, und reagiert entsprechend. Ich würde hoffen, dass es für die clientseitige Programmierung etwas Ähnliches gibt ... wenn nötig sogar nur eine "isDebug" -Variable setzen. Warum sollte ich den nächsten Entwickler belasten wollen, indem ich in Zukunft die Protokollierung für problematische Bereiche erneut hinzufügen muss?
Sean Anderson
11
Schäbig wie? Ich würde argumentieren, dass die Aussage, dass die Entwicklerkonsole Teil der Produktionswebsite ist, der Aussage entspricht, dass die Protokolldateien Teil einer Anwendung sind. Ja, beide werden durch Code generiert, aber es sollte ein gewisses Maß an Verständnis dafür bestehen, dass Protokolle irgendwo belassen werden müssen. Ob die Anweisungen in den Protokollen benutzerfreundlich sind oder nicht, ist jedoch eine andere Frage.
Sean Anderson
4
Wie würde man Debugging-Code automatisch entfernen, bevor man ihn minimiert? Es gibt eine große Anzahl von Formularen, die eine clientseitige Protokollnachricht annehmen kann.
Sean Anderson
6
Sie können jeden Debug-Code markieren, indem Sie beispielsweise eine Zeile Debug-Code durch einen Kommentar voranstellen / nachfixieren. Beispiel : /*DEBUG:start*/console.log("Foo");/*DEBUG:end*/. Verwenden Sie dann ein RegExp, um alle Vorkommen von zu entfernen /*DENUG-start*/[\S\s]*?/*DEBUG-end*/. Die verbleibenden Leerzeichen werden vom Minimierer entfernt.
Rob W
3
Wenn diese Antwort nicht sagt, WARUM Sie es nicht tun sollten, ist es wirklich nicht nützlich. Wir sollen nur blind akzeptieren, dass es schlecht ist, ohne Beweise oder Gründe?
ESR
48

Eine andere Möglichkeit, damit umzugehen, besteht darin, das Konsolenobjekt zu "stubben", wenn es nicht definiert ist, damit in Kontexten, in denen die Konsole nicht vorhanden ist, keine Fehler ausgegeben werden

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

Sie erhalten die Idee ... es gibt eine Menge von Funktionen auf den verschiedenen Implementierungen der Konsole definiert sind, so könnte man sie alle oder nur die , die Sie verwenden (zB wenn Sie jemals verwenden Stummel console.logund nie benutzt console.profile, console.timeetc ...)

Dies ist für mich eine bessere Alternative in der Entwicklung, als vor jedem Anruf Bedingungen hinzuzufügen oder diese nicht zu verwenden.

Siehe auch: Ist es eine schlechte Idee, "console.log ()" - Aufrufe in Ihrem Produkt auf JavaScript-Code zu belassen?

craigb
quelle
6
Gute Idee. Nur einige Korrekturen erforderlich. Der Visual Studio JS-Debugger löst die erste console.log = noOp () aus, da das Konsolenobjekt selbst nicht definiert ist. Ich habe es so gemacht: console = {log: noOp, warn: noOp, error: noOp}. Beachten Sie auch, dass Sie nicht () nach noOp setzen möchten - Sie möchten die Funktion selbst und nicht ihren Rückgabewert zuweisen. Getestet mit Visual Studio JS Debugger und IE9 - jetzt funktioniert es einwandfrei.
JustAMartin
3
Zu Ihrer Information, wenn Sie bereits jQuery verwenden, bieten sie eine Noop-Funktion : $.noop.
Crush
28

UglifyJS2

Wenn Sie diesen Minifier verwenden, können Sie folgende drop_consoleOptionen festlegen :

Übergeben Sie true, um Aufrufe an die Konsolenfunktionen zu verwerfen. *

Daher würde ich vorschlagen, console.logAnrufe so zu belassen, wie sie für einen der schwierigsten Teile der Codebasis sind.

terales
quelle
3
Wenn Sie grunt und uglify verwenden , ist dieselbe Option ebenfalls verfügbar (anscheinend basiert uglify auf UglifyJS2): github.com/gruntjs/…
Tilt
1
Die Frage ist "sollte ich", nicht "wie mache ich".
ESR
Sie sollten console.errors in lassen. Wenn jemand in der Produktion ein Problem hat, können Sie es leicht diagnostizieren. Konsole nicht ausziehen. Fehler!
Oliver Watkins
Wenn es eine Notwendigkeit für sie sein , dann können Sie nur einstellen drop_consolezu false, beobachten sie und verstecken sie wieder.
Terales
16

Wenn die Minimierung Teil Ihres Erstellungsprozesses ist, können Sie damit Debug-Code entfernen, wie hier mit dem Google Closure Compiler erläutert: Schließen Sie den Debug-JavaScript-Code während der Minimierung aus

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

Wenn Sie mit erweiterten Optimierungen kompilieren, wird dieser Code sogar als tot identifiziert und vollständig entfernt

wutz
quelle
1
Danke dir! Ich habe danach gesucht. :)
Sean Anderson
5

Ja. console.log löst in Browsern, die dies nicht unterstützen, eine Ausnahme aus (Konsolenobjekt wird nicht gefunden).

MK_Dev
quelle
nicht mit seiner Kurzschlussbewertung, solange das Fenster definiert ist
Joe
1
Obwohl ich es in meiner ersten Antwort verpasst habe, sollte auch nach console.log gesucht werden.
MK_Dev
Ich mache meistens nur die window.console, um Ärger mit dem IE zu vermeiden. Ich bin noch nicht in eine Situation geraten, in der das Protokoll unbeabsichtigt überschrieben wurde, aber ich bin mir sicher, dass dies passieren könnte.
Sean Anderson
@MK_Dev Nämlich, welche Browser?
Goodpixel
Es ist 2019. Ich bezweifle, dass es Browser gibt, die keine Konsole unterstützen.
Oliver Watkins
5

Im Allgemeinen ist es keine gute Idee, Protokollnachrichten in Ihrem Produktionscode verfügbar zu machen.

Idealerweise sollten Sie solche Protokollnachrichten vor der Bereitstellung mit einem Build-Skript entfernen. Aber viele (die meisten) Leute verwenden keinen Build-Prozess (einschließlich mir).

Hier ist ein kurzer Ausschnitt eines Codes, den ich in letzter Zeit verwendet habe, um dieses Dilemma zu lösen. Es behebt Fehler, die durch einen undefinierten consoleim alten IE verursacht wurden, und deaktiviert die Protokollierung, wenn im "Entwicklungsmodus".

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

Ich bin mir ziemlich sicher, dass ich viel von dem oben genannten addConsoleNoOpf'n aus einer anderen Antwort auf SO genommen habe, kann es aber momentan nicht finden. Ich werde später eine Referenz hinzufügen, wenn ich sie finde.

edit: Nicht der Beitrag, an den ich gedacht habe, aber hier ist ein ähnlicher Ansatz: https://github.com/paulmillr/console-polyfill/blob/master/index.js

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

Verwendung:

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

Ja, es wird console.logempfohlen, es für das Debuggen von Javascript zu verwenden, aber es muss vom Produktionsserver entfernt werden oder kann bei Bedarf auf dem Produktionsserver hinzugefügt werden, wobei einige wichtige Punkte zu berücksichtigen sind:

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

Der obige Codeblock muss überall für die Protokollierung verwendet werden, um zunächst zu überprüfen, ob die Konsole für den aktuellen Browser unterstützt wird und ob das Debuggen aktiviert ist oder nicht.

isDebugEnabled muss basierend auf unserer Umgebung als wahr oder falsch festgelegt werden.

shanky
quelle
1

TL; DR

Idee: Das Protokollieren von Objekten verhindert, dass sie durch Müll gesammelt werden.

Einzelheiten

  1. Wenn Sie Objekte an übergeben, können Sie auf console.logdiese Objekte über die Konsole von DevTools zugreifen. Sie können dies überprüfen, indem Sie das Objekt protokollieren, es mutieren und feststellen, dass alte Nachrichten spätere Änderungen des Objekts widerspiegeln.
  2. Wenn die Protokolle zu lang sind, werden alte Nachrichten in Chrome gelöscht.
  3. Wenn die Protokolle kurz sind, werden alte Nachrichten nicht entfernt. Wenn diese Nachrichten auf Objekte verweisen, werden diese Objekte nicht durch Garbage Collected erfasst.

Es ist nur eine Idee: Ich habe die Punkte 1 und 2 überprüft, aber nicht 3.

Lösung

Wenn Sie Protokolle zur clientseitigen Fehlerbehebung oder für andere Anforderungen führen möchten, gehen Sie wie folgt vor:

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

Grundsätzlich überschreibe ich die Funktion console.log mit der Funktion, die weiß, wo der Code ausgeführt wird. Somit kann ich console.log wie immer weiter verwenden. Es weiß automatisch, dass ich mich im Dev / Qa-Modus oder in der Produktion befinde. Es gibt auch eine Möglichkeit, dies zu erzwingen. Hier ist eine funktionierende Geige. http://jsfiddle.net/bsurela/Zneek/

Hier ist das Snippet, da der Stapelüberlauf von Leuten angedeutet wird, die jsfiddle posten

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

Ich weiß, dass dies eine ziemlich alte Frage ist und seit einiger Zeit nicht mehr viel Aktivität hatte. Ich wollte nur meine Lösung hinzufügen, die ich mir ausgedacht habe und die für mich recht gut zu funktionieren scheint.

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

Dann erstelle ich normalerweise eine Funktion in meinen Skripten wie diese oder Sie können sie in einem globalen Skript verfügbar machen:

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

Und dann benutze ich das einfach anstelle von console.log wie folgt:

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
quelle