프로덕션 코드에서 console.log를 제거해야합니까?


88

현재 코드의 모든 곳에이 JS 문이 있습니다.

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

이것이 비용이 많이 들거나 생산에 부정적인 부작용이 있는지 궁금합니다.

클라이언트 측 로그인을 그대로 둘 수 있습니까? 아니면 계속해야합니까?

편집 : 결국, 나 (그리고 다른 사람?)가 생각 해낼 수있는 가장 좋은 주장은 로깅 메시지를 남겨 두어 서버와 클라이언트간에 전송되는 추가 데이터의 양이 무시할 수 없을 정도로 많다는 것입니다. 프로덕션 코드는 완전히 최적화되어야하며, 클라이언트로 전송되는 javascript의 크기를 줄이려면 로깅을 제거해야합니다.


답변:


41

프로덕션 페이지에 개발 도구를 추가 해서는 안됩니다 .

다른 질문에 답하려면 : 코드는 부정적인 부작용을 가질 수 없습니다.

  • window.consoleconsole정의되지 않은 경우 false로 평가 됩니다.
  • console.log("Foo")정의 될 때 콘솔에 메시지를 인쇄합니다 (페이지가 console.log비 기능으로 덮어 쓰이지 않는 경우 ).

43
원칙적으로 동의합니다. 그러나 나는 디버그 모드를 제외하고는 실행되지 않는 로깅을 구현하는 것이 양질의 서버 측 코드를 위해 필요하다는 데 모두 동의 할 것이라고 생각합니다. 아무도 프로덕션 릴리스에 대한 로깅을 거치지 않고 제거하지 않습니다. 프로그램은 필요한 로깅 수준을 결정하고 그에 따라 반응합니다. 클라이언트 측 프로그래밍에 이와 비슷한 것이 있기를 바랍니다. 필요한 경우 "isDebug"변수 만 설정해도됩니다. 앞으로 돌아가서 문제가있는 영역에 대한 로깅을 다시 추가해야하는 이유는 다음 개발자에게 부담이 될까요?
Sean Anderson

11
어떻게 초라한? 개발자 콘솔이 프로덕션 웹 사이트의 일부라고 말하는 것은 로그 파일이 애플리케이션의 일부라고 말하는 것과 같습니다. 예, 둘 다 코드에 의해 생성되지만 로그를 어딘가에 두어야한다는 것을 어느 정도 이해해야합니다. 로그 안의 문장이 사용자 친화적인지 아닌지는 또 다른 문제입니다.
Sean Anderson

4
최소화하기 전에 디버깅 코드를 자동으로 제거하는 방법은 무엇입니까? 클라이언트 측 로그 메시지가 취할 수있는 많은 양식이 있습니다.
Sean Anderson

6
예를 들어, 주석으로 디버깅 코드 줄을 접두사 / 접미사로 붙여 모든 디버그 코드를 표시 할 수 있습니다. 예 : /*DEBUG:start*/console.log("Foo");/*DEBUG:end*/. 그런 다음 RegExp를 사용하여 /*DENUG-start*/[\S\s]*?/*DEBUG-end*/. 나머지 공백 문자는 최소화기에 의해 제거됩니다.
Rob W

3
이 답변이 왜 그렇게하면 안되는지를 말하지 않는 한 실제로 유용하지 않습니다. 증거 나 이유없이 그것이 나쁘다는 것을 맹목적으로 받아 들여야하는 건가요?
ESR

49

이를 처리하는 또 다른 방법은 콘솔 객체가 정의되지 않았을 때 콘솔 객체를 '스텁'하여 콘솔이없는 컨텍스트에서 오류가 발생하지 않도록하는 것입니다.

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

아이디어를 얻을 수 있습니다 ... 콘솔의 다양한 구현에 정의 된 많은 함수가 있으므로 모두 또는 사용하는 기능 만 스텁 할 수 있습니다 (예 : 사용 console.log하고 사용 하지 않은 console.profile경우 console.time등).

이것은 모든 호출 앞에 조건문을 추가하거나 사용하지 않는 것보다 개발에서 더 나은 대안입니다.

참조 : "console.log ()"호출을 JavaScript 코드에 그대로 두는 것이 나쁜 생각입니까?


6
좋은 생각. 몇 가지 수정이 필요합니다. Visual Studio JS 디버거는 콘솔 개체 자체가 정의되지 않았기 때문에 첫 번째 console.log = noOp ()에서 발생합니다. 나는 다음과 같이했다 : console = {log : noOp, warn : noOp, error : noOp}. 또한 noOp 뒤에 ()를 넣지 않고 반환 값이 아닌 함수 자체를 할당하려고합니다. Visual Studio JS 디버거 및 IE9에서 테스트-이제 정상적으로 작동합니다.
JustAMartin 2013 년

3
참고로 이미 jQuery를 사용하고 있다면 noop 기능을 제공합니다 $.noop.
분쇄

28

UglifyJS2

이 minifier를 사용하는 경우 drop_console옵션 을 설정할 수 있습니다 .

console. * 함수에 대한 호출을 버리려면 true를 전달하십시오.

따라서 console.log코드베이스에서 가장 까다로운 부분에 대한 호출 을 남겨 두는 것이 좋습니다 .


3
당신이 사용하는 경우 꿀꿀 거리는 소리추하게 같은 옵션 (추하게이 UglifyJS2를 기반으로 보인다)도 주문 가능합니다 github.com/gruntjs/...
틸트

1
질문은 "어떻게해야합니까"가 아니라 "내가해야합니까"입니다.
ESR

console.errors는. 생산중인 누군가에게 문제가 있으면 쉽게 진단 할 수 있습니다. 콘솔을 제거하지 마십시오.
Oliver Watkins

필요한 경우으로 설정 drop_console하고 false관찰 한 다음 다시 숨길 수 있습니다.
terales

16

축소가 빌드 프로세스의 일부인 경우 여기에 Google 클로저 컴파일러에 설명 된대로 디버그 코드를 제거하는 데 사용할 수 있습니다. 축소 중 디버그 자바 스크립트 코드 제외

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

고급 최적화로 컴파일하는 경우이 코드는 죽은 것으로 식별되어 완전히 제거됩니다.


1
감사합니다! 나는 이것을 찾고 있었다. :)
Sean Anderson

5

예. console.log는이를 지원하지 않는 브라우저에서 예외를 발생시킵니다 (콘솔 객체는 찾을 수 없음).


기간이 정의되어있는 한 단락 평가와 함께하지 않음
Joe

1
초기 답변에서 놓쳤지만 console.log도 확인해야합니다.
MK_Dev

IE와의 번거 로움을 방지하기 위해 주로 window.console을 수행합니다. 의도 치 않게 로그가 무시되는 상황은 아직 발생하지 않았지만 일어날 수 있다고 확신합니다.
Sean Anderson

@MK_Dev 즉, 어떤 브라우저입니까?
goodpixels

2019 년입니다. 콘솔을 지원하지 않는 브라우저는 없을 것 같습니다.
Oliver Watkins 19

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

나는 위의 addConsoleNoOpf'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.log자바 스크립트 디버깅 목적 으로 사용하는 것이 좋지만 프로덕션 서버에서 제거하거나 필요한 경우 몇 가지 핵심 사항을 고려하여 프로덕션 서버에 추가 할 수 있습니다.

**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 환경에 따라 참 또는 거짓으로 설정해야합니다.


1

TL; DR

아이디어 : 개체를 로깅하면 가비지 수집에서 제외됩니다.

세부

  1. 객체를 전달하면 console.logDevTools의 콘솔에서 참조를 통해 이러한 객체에 액세스 할 수 있습니다. 객체를 로깅하고, 변경하고, 오래된 메시지가 이후의 객체 변경 사항을 반영하는지 확인하여 확인할 수 있습니다.
  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이 아니라 자동화 된 적이 있었다.

같은 현대적인 프레임 워크의 많은 Angular, React, Svelte, Vue.js아웃 - 오브 - 박스가 설치 함께 제공됩니다. 올바른 빌드, 즉, 배포 등 기본적으로, 당신은 오래로, 아무것도 할 필요가 없습니다 production하나하지 development여전히있을 것이다 console.log.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.