Исключить отладочный код JavaScript во время минификации - PullRequest
40 голосов
/ 29 мая 2010

Я изучаю различные способы минимизации своего кода JavaScript, включая обычные решения JSMin , Packer и YUI . Я действительно заинтересован в новом Google Closure Compiler , так как он выглядит исключительно мощным.

Я заметил, что Упаковщик Дина Эдвардса имеет функцию исключения строк кода, которые начинаются с трех точек с запятой. Это удобно для исключения кода отладки. Например:

;;;     console.log("Starting process");

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

Поскольку я еще не выбрал способ минимизации, я бы хотел очистить код таким образом, чтобы он был совместим с любым минификатором, с которым я в итоге столкнулся. Итак, мои вопросы таковы:

  1. Является ли использование точек с запятой стандартной техникой или есть другие способы сделать это?

  2. Является ли Packer единственным решением, обеспечивающим эту функцию?

  3. Могут ли другие решения быть адаптированы для работы таким же образом, или у них есть альтернативные способы сделать это?

  4. Скорее всего, я начну использовать Closure Compiler. Есть ли что-то, что я должен сделать сейчас, чтобы подготовиться к этому?

Ответы [ 10 ]

58 голосов
/ 11 мая 2011

вот (окончательный) ответ для компилятора замыкания:

/** @const */
var LOG = false;
...
LOG && log('hello world !'); // compiler will remove this line
...

это будет работать даже с SIMPLE_OPTIMIZATIONS, и --define= не требуется!

25 голосов
/ 08 июля 2010

Вот что я использую с Closure Compiler. Во-первых, вам нужно определить переменную DEBUG следующим образом:

/** @define {boolean} */
var DEBUG = true;

Он использует аннотацию JS для закрытия, о которой вы можете прочитать в документации .

Теперь, когда вам нужен какой-то отладочный код, просто оберните его в оператор if, например:

if (DEBUG) {
  console.log("Running in DEBUG mode");
}

При компиляции кода для выпуска добавьте следующую команду компиляции: --define='DEBUG=false' - любой код в операторе отладки будет полностью исключен из скомпилированного файла.

6 голосов
/ 29 мая 2010

Хорошим решением в этом случае может быть js-build-tools , который поддерживает «условную компиляцию».

Короче говоря, вы можете использовать комментарии, такие как

// #ifdef debug
var trace = debug.getTracer("easyXDM.Rpc");
trace("constructor");
// #endif

где вы определяете прагму, такую ​​как debug.

Тогда при его создании (у него есть муравейник)

//this file will not have the debug code
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.js"/>
//this file will        
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.debug.js" defines="debug"/>
2 голосов
/ 24 июля 2015

Добавление логики в каждое место вашего кода, куда вы входите в консоль, усложняет отладку и обслуживание.

Если вы уже собираетесь добавить шаг сборки для своего производственного кода, вы всегда можете добавить еще один файл вверху, который превращает ваши console методы в noop.

Что-то вроде:

console.log = console.debug = console.info = function(){};

В идеале, вы бы просто удалили любые console методы, но если вы все равно сохраняете их, но не используете, это, вероятно, самый простой для работы.

2 голосов
/ 25 февраля 2014

Если вы используете UglifyJS2 , вы можете использовать аргумент drop_console для удаления консоли. * Functions.

2 голосов
/ 01 марта 2012

Хотя это старый вопрос. Сегодня я столкнулся с той же проблемой и обнаружил, что ее можно решить с помощью CompilerOptions .

.

Я подписался на эту тему .

Мы запускаем компилятор из Java на нашем сервере перед отправкой кода клиенту. Это работало для нас в простом режиме.

private String compressWithClosureCompiler(final String code) {
    final Compiler compiler = new Compiler();
    final CompilerOptions options = new CompilerOptions();
    Logger.getLogger("com.google.javascript.jscomp").setLevel(Level.OFF);
    if (compressRemovesLogging) {
        options.stripNamePrefixes = ImmutableSet.of("logger");
        options.stripNameSuffixes = ImmutableSet.of("debug", "dev", "info", "error",
                "warn", "startClock", "stopClock", "dir");
    }
    CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);

    final JSSourceFile extern = JSSourceFile.fromCode("externs.js", "");
    final JSSourceFile input = JSSourceFile.fromCode("input.js", code);
    compiler.compile(extern, input, options);
    return compiler.toSource();
}

Он удалит все вызовы logger.debug, logger.dev ... и т. Д. И т. Д.

2 голосов
/ 10 марта 2011

Если вы используете компилятор Closure в расширенном режиме, вы можете сделать что-то вроде:

if (DEBUG) console.log = function() {}

Тогда компилятор удалит все ваши вызовы console.log. Конечно, вам нужно --define переменная DEBUG в командной строке.

Однако, это только для Расширенный режим . Если вы используете простой режим, вам нужно запустить препроцессор для вашего исходного файла.

Почему бы не рассмотреть Dojo Toolkit? Он имеет встроенную прагму на основе комментариев для включения / исключения разделов кода, основанных на сборке. Кроме того, он совместим с компилятором Closure в расширенном режиме (см. Ссылку ниже)!

http://dojo -toolkit.33424.n3.nabble.com / файл / n2636749 / Using_the_Dojo_Toolkit_with_the_Closure_Compiler.pdf? По-пользователя = т

1 голос
/ 05 ноября 2015

Я с @ marcel-korpel. Не идеально, но работает. Замените инструкции по отладке перед минификацией. Регулярное выражение работает во многих местах. Остерегайтесь незакрытых линий.

/console\.[^;]*/gm

Работает на:

;;;     console.log("Starting process");
console.log("Starting process");
console.dir("Starting process");;;;;
console.log("Starting "+(1+2)+" processes"); iamok('good');
console.log('Message ' +
    'with new line'
);
console.group("a");
console.groupEnd();
swtich(input){
    case 1 : alert('ok'); break;
    default: console.warn("Fatal error"); break;
}

Не работает:

console.log("instruction without semicolon")
console.log("semicolon in ; string");
0 голосов
/ 19 февраля 2012

Я использовал следующие самодельные вещи:

// Uncomment to enable debug messages
// var debug = true;

function ShowDebugMessage(message) {
    if (debug) {
        alert(message);
    }
}

Таким образом, когда вы объявили переменную debug, которая установлена ​​в true - все ShowDebugMessage() вызовы также вызовут alert(). Так что просто используйте его в коде и забудьте о таких условиях, как ifdef или ручное комментирование строк отладочной информации.

0 голосов
/ 29 мая 2010

До сих пор я не изучал минификацию, но такое поведение можно реализовать с помощью простого регулярного выражения:

s/;;;.*//g

Это заменяет все в строке после (и включая) три точки с запятой ничем, поэтому оно отбрасывается перед минификацией. Вы можете запустить sed (или аналогичный инструмент) перед запуском инструмента минимизации, например:

sed 's/;;;.*//g' < infile.js > outfile.js

Кстати, если вам интересно, будет ли «лучше» упакованная или уменьшенная версия, прочитайте это сравнение методов сжатия JavaScript .

...