プロダクションコードからconsole.logを削除する必要がありますか?


86

私は現在、コードのいたるところにこのJSステートメントを持っています:

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

これはまったく費用がかかるのか、それとも生産にマイナスの副作用があるのか​​疑問に思います。

クライアント側のログインをそのままにしておくことはできますか、それとも続行する必要がありますか?

編集:結局、私(そして他の誰か?)が思いつくことができる最良の議論は、ロギングメッセージを残してサーバーとクライアントの間で転送される余分なデータの量が無視できない可能性があるということだと思います。本番コードは完全に最適化する必要があります。クライアントに送信されるJavaScriptのサイズを減らすために、ロギングを削除する必要があります。


回答:


41

あなたはすべきではない、生産ページに開発ツールを追加します。

他の質問に答えるには:コードに悪影響を与えることはできません。

  • window.consoleconsole定義されていない場合はfalseと評価されます
  • console.log("Foo")定義されたときにメッセージをコンソールに出力します(ページがconsole.log非関数によって上書きされない場合)。

43
原則として同意します。しかし、高品質のサーバーサイドコードには、デバッグモード以外では起動しないロギングを実装する必要があることに同意すると思います。本番リリースのログを調べて削除する人は誰もいません。プログラムは、必要なログのレベルを決定し、それに応じて対応します。クライアント側のプログラミングには、これに似たものがあるといいのですが...必要に応じて「isDebug」変数を設定するだけでもかまいません。将来、問題のある領域に戻ってログを再度追加する必要があるため、次の開発者に負担をかけたいのはなぜですか?
ショーンアンダーソン

11
ぼろぼろの方法?開発者コンソールが本番Webサイトの一部であると言うことは、ログファイルがアプリケーションの一部であると言うことに似ていると私は主張します。はい、どちらもコードによって生成されますが、ログをどこかに残しておく必要があることをある程度理解する必要があります。ただし、ログ内のステートメントがユーザーフレンドリーであるかどうかは別の問題です。
ショーンアンダーソン

4
最小化する前に、デバッグコードを自動的に削除するにはどうすればよいですか?クライアント側のログメッセージが取ることができるフォームはたくさんあります。
ショーンアンダーソン

6
たとえば、デバッグコードの行の前後にコメントを付けることで、デバッグコードのすべての部分にマークを付けることができます。例:/*DEBUG:start*/console.log("Foo");/*DEBUG:end*/。次に、RegExpを使用して、のすべての出現箇所を削除します/*DENUG-start*/[\S\s]*?/*DEBUG-end*/。残りの空白文字は、最小化によって削除されます。
ロブW

3
この答えがなぜあなたがそれをすべきでないのかを言わない限り、それは本当に役に立ちません。証拠も理由もなく、それが悪いことを盲目的に受け入れることになっているだけですか?
ESR

48

これに対処する別の方法は、コンソールオブジェクトが定義されていないときにコンソールオブジェクトを「スタブ」して、コンソールがないコンテキストでエラーがスローされないようにすることです。

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

あなたはアイデアを得る...コンソールのさまざまな実装で定義された多くの関数があるので、それらすべてまたは使用するものだけをスタブ化することができます(たとえば、使用console.logしたことがありconsole.profile、使用したことがない場合console.timeなど)

私にとってこれは、すべての呼び出しの前に条件文を追加したり、条件文を使用しないよりも、開発におけるより良い代替手段です。

参照: JavaScriptコードの製品に「console.log()」呼び出しを残すのは悪い考えですか?


6
良いアイデア。いくつかの修正が必要です。コンソールオブジェクト自体が定義されていないため、Visual StudioJSデバッガーは最初のconsole.log = noOp()をスローします。私は次のようにしました:console = {log:noOp、warn:noOp、error:noOp}。また、noOpの後に()を付けたくないことにも注意してください。戻り値ではなく、関数自体を割り当てたいのです。Visual StudioJSデバッガーとIE9でテスト済み-正常に動作するようになりました。
JustAMartin 2013年

3
参考までに、すでにjQueryを使用している場合は、noop関数を提供します$.noop
2015年

28

UglifyJS2

このミニファイアを使用している場合は、drop_consoleオプションを設定できます

trueを渡すと、console。*関数への呼び出しが破棄されます。

したがってconsole.log、コードベースの最もトリッキーな部分の呼び出しをそのままにしておくことをお勧めし ます。


3
あなたが使用している場合はうなり声をしてuglify、同じオプションが(uglifyがUglifyJS2に基づいているようだ)もご覧になれます。github.com/gruntjs/...
チルト

1
問題は、「どうすればよいか」ではなく、「私がすべきか」です。
ESR

console.errorsはに残しておく必要があります。本番環境の誰かに問題がある場合は、簡単に診断できます。console.errorsを削除しないでください!
オリバーワトキンス

それらが必要な場合は、に設定drop_consolefalse、それらを観察して、再度非表示にすることができます。
terales

16

ミニファイがビルドプロセスの一部である場合は、Googleクロージャーコンパイラでここで説明されているように、それを使用してデバッグコードを取り除くことができます。ミニファイ中にデバッグJavaScriptコードを除外する

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

高度な最適化を使用してコンパイルすると、このコードは無効であると識別され、完全に削除されます。


1
ありがとうございました!私はこれを探していました。:)
ショーンアンダーソン

5

はい。console.logは、それをサポートしていないブラウザで例外をスローします(コンソールオブジェクトは見つかりません)。


ウィンドウが定義されている限り、彼の短絡評価ではありません
Joe

1
最初の回答では見逃していましたが、console.logも確認する必要があります。
MK_Dev 2011年

私は主に、IEでの煩わしさを防ぐためにwindow.consoleを実行します。意図せずにログが上書きされるという状況にはまだ遭遇していませんが、発生する可能性があると確信しています。
ショーンアンダーソン

@MK_Devつまり、どのブラウザですか?
goodpixels

2019年です。コンソールをサポートしていないブラウザはないと思います。
オリバーワトキンス

5

一般的にはそうです。本番コードでログメッセージを公開するのは良い考えではありません。

理想的には、展開前にビルドスクリプトを使用してこのようなログメッセージを削除する必要があります。しかし、多くの(ほとんどの)人々はビルドプロセスを使用していません(私を含む)。

これは、このジレンマを解決するために最近使用しているコードの短い抜粋です。console古いIEで未定義が原因で発生したエラーを修正し、「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);
}

私は上記の多くを取ったことをかなり確信しています addConsoleNoOpSOに関する別の回答からf'nの取得したと確信していますが、現時点では見つかりません。見つかった場合は、後で参照を追加します。

編集:私が考えていた投稿ではありませんが、同様のアプローチがあります: 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;
})();

使用法:

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

1

はい、console.logJavaScriptのデバッグ目的で使用することをお勧めしますが、本番サーバーから削除するか、必要に応じて、いくつかの重要なポイントを考慮して本番サーバーに追加できます。

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

コンソールが現在のブラウザでサポートされているかどうか、およびデバッグが有効になっているかどうかを最初に確認するために、上記のコードブロックをログ記録にどこでも使用する必要があります。

isDebugEnabled 環境に基づいてtrueまたはfalseに設定する必要があります。


1

TL; DR

考え:オブジェクトをログに記録すると、ガベージコレクションができなくなります。

詳細

  1. オブジェクトをに渡す場合 console.log、これらのオブジェクトはDevToolsのコンソールから参照によってアクセスできます。オブジェクトをログに記録し、変更して、古いメッセージがオブジェクトのその後の変更を反映していることを確認することで、それを確認できます。
  2. ログが長すぎる場合、古いメッセージはChromeで削除されます。
  3. ログが短い場合、古いメッセージは削除されません。これらのメッセージがオブジェクトを参照している場合、これらのオブジェクトはガベージコレクションされません。

それは単なるアイデアです。ポイント1と2をチェックしましたが、3はチェックしませんでした。

解決

クライアント側のトラブルシューティングやその他のニーズのためにログを保持したい場合は、次のようにします。

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

0

基本的に、console.log関数を、コードが実行されている場所を認識している関数で上書きします。したがって、いつものようにconsole.logを使い続けることができます。私がdev / qaモードまたは本番環境にあることを自動的に認識します。それを強制する方法もあります。これが実用的なフィドルです。 http://jsfiddle.net/bsurela/Zneek/

スタックオーバーフローは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

これはかなり古い質問であり、しばらくの間あまり活動がなかったことを私は知っています。私が思いついたソリューションを追加したかったのですが、それは私にとって非常にうまくいくようです。

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

次に、通常、次のようなスクリプトで関数を作成します。または、グローバルスクリプトで使用できるようにすることもできます。

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

そして、次のように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);
}

0

parcel/などの適切なツールを使用してワークフローを実行するwebpackと、productionビルドconsole.logが削除されるため、頭痛の種ではなくなります。数年前でもGulp/Gruntで自動化できたはずです。

このような近代的なフレームワークの多くはAngularReactSvelteVue.jsすぐにその設定が付属しています。基本的に、正しいビルド、つまりproductiondevelopmentまだ存在しないビルドをデプロイする限り、何もする必要はありませんconsole.log

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.