Следует ли мне удалить console.log из производственного кода?

86

В настоящее время в моем коде есть этот JS-оператор:

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

Мне интересно, стоит ли это вообще дорого или имеет какие-либо отрицательные побочные эффекты при производстве.

Могу ли я оставить вход на стороне клиента или он должен уйти?

РЕДАКТИРОВАТЬ: В конце концов, я полагаю, что лучший аргумент, который я (и кто-либо еще?) Мог бы придумать, заключается в том, что существует, возможно, немаловажное количество дополнительных данных, передаваемых между сервером и клиентом, оставляя сообщения журнала оставленными. Если производственный код должен быть полностью оптимизирован, ведение журнала необходимо удалить, чтобы уменьшить размер javascript, отправляемого клиенту.

Шон Андерсон
источник

Ответы:

41

Вам не следует добавлять инструменты разработки на рабочую страницу.

Чтобы ответить на другой вопрос: код не может иметь отрицательного побочного эффекта:

  • window.consoleбудет оцениваться как false, если consoleне определено
  • console.log("Foo")будет выводить сообщение на консоль, когда оно определено (при условии, что страница не перезаписывается console.logне-функцией).
Роб В
источник
43
Я согласен с вами в принципе. Но я думаю, мы все согласимся с тем, что для качественного серверного кода необходима реализация ведения журнала, который не срабатывает, кроме как в режиме отладки. Никто не просматривает и не удаляет свои журналы для производственной версии - программа определяет, какой уровень ведения журнала необходим, и реагирует соответствующим образом. Я надеюсь, что есть что-то похожее на это для программирования на стороне клиента ... даже просто установив переменную isDebug, если это необходимо. Зачем мне обременять следующего разработчика, заставляя возвращаться и повторно добавлять ведение журнала для проблемных областей в будущем?
Шон Андерсон
11
Потрепанный как? Я бы сказал, что сказать, что консоль разработчика является частью производственного веб-сайта, все равно что сказать, что файлы журнала являются частью приложения. Да, они оба генерируются кодом, но должен быть некоторый уровень понимания того, что журналы нужно где-то оставлять. Однако другой вопрос, являются ли операторы внутри журналов удобными для пользователя или нет.
Шон Андерсон
4
Как можно автоматически удалить отладочный код перед сворачиванием? Сообщение журнала на стороне клиента может принимать большое количество форм.
Шон Андерсон
6
Вы можете пометить каждый фрагмент отладочного кода, например, добавив к строке отладочного кода префикс / постфикс в виде комментария. Пример: /*DEBUG:start*/console.log("Foo");/*DEBUG:end*/. Затем используйте RegExp, чтобы удалить все вхождения /*DENUG-start*/[\S\s]*?/*DEBUG-end*/. Остальные символы пробела будут удалены минимизатором.
Rob 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т. д.)

Для меня это лучшая альтернатива при разработке, чем добавление условных обозначений перед каждым вызовом или их неиспользование.

см. также: Оставлять вызовы console.log () в коде JavaScript в вашем продукте - плохая идея?

Craigb
источник
6
Хорошая идея. Требуются лишь некоторые исправления. Отладчик Visual Studio JS выдает в первой строке console.log = noOp (), поскольку сам объект консоли не определен. Я сделал это так: console = {log: noOp, warn: noOp, error: noOp}. Также обратите внимание, что вы не хотите помещать () после noOp - вы хотите назначить саму функцию, а не ее возвращаемое значение. Протестировано на отладчике Visual Studio JS и IE9 - теперь все работает нормально.
JustAMartin
3
FYI, если вы уже используете JQuery, они обеспечивают функцию Nööp: $.noop.
Crush
28

UglifyJS2

Если вы используете этот минификатор, вы можете установить drop_consoleопцию :

Передайте true, чтобы отклонить вызовы функций console. *

Поэтому я бы посоветовал оставить console.logвызовы как есть для самой сложной части кодовой базы.

тералес
источник
3
Если вы используете grunt и uglify , этот же вариант также доступен (кажется, что uglify основан на UglifyJS2): github.com/gruntjs/…
Tilt
1
Вопрос в том, «должен ли я», а не «как мне».
ESR
Вы должны оставить console.errors в. Если у кого-то на производстве возникла проблема, вы легко сможете ее диагностировать. Не удаляйте console.errors!
Оливер Уоткинс
Если будет необходимость в них , то вы можете просто установить , drop_consoleчтобы falseсоблюдать их и снова скрыть их.
terales
16

Если минификация является частью процесса сборки, вы можете использовать ее для удаления кода отладки, как описано здесь с помощью компилятора закрытия Google: Исключить код отладки JavaScript во время минификации

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

Если вы компилируете с расширенной оптимизацией, этот код даже будет идентифицирован как мертвый и полностью удален.

Wutz
источник
1
Спасибо! Я искал это. :)
Шон Андерсон
5

Да. console.log вызовет исключение в браузерах, которые его не поддерживают (объект консоли не будет найден).

MK_Dev
источник
не с его оценкой короткого замыкания, пока определено окно
Джо
1
Хотя я пропустил это в своем первоначальном ответе, также следует проверить console.log.
MK_Dev 03
Я в основном просто использую window.console, чтобы избежать проблем с IE. Мне еще предстоит столкнуться с ситуацией, когда журнал случайно переопределился, но я уверен, что это могло произойти.
Шон Андерсон
@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);
}

Я почти уверен, что взял большую часть приведенного выше addConsoleNoOpf'n из другого ответа на SO, но не могу найти прямо сейчас. Я добавлю ссылку позже, если найду.

edit: Не тот пост, о котором я думал, но вот аналогичный подход: 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');
Dynamiclynk
источник
1

Да, это хорошая практика для использования console.logдля целей отладки javascript, но ее необходимо удалить с производственного сервера или, при необходимости, можно добавить на производственный сервер с учетом некоторых ключевых моментов:

**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.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это тоже можно было автоматизировать.

Многие из современных систем , такие , как Angular, React, Svelte, Vue.jsприходят с этой установкой вне коробки. По сути, вам не нужно ничего делать, пока вы развертываете правильную сборку, то есть productionту, developmentкоторая еще не будет console.log.

Даниэль Даниелецки
источник