Исключить код отладки JavaScript во время минимизации

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

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

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

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

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

  • Использует ли точка с запятой стандартную технику или есть другие способы сделать это?

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

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

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

Ответы

Ответ 1

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

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

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

Ответ 2

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

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

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

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

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

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

Ответ 3

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

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

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

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

Затем при его создании (у него есть ant -task)

//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"/>

Ответ 4

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

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

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

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

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

http://dojo-toolkit.33424.n3.nabble.com/file/n2636749/Using_the_Dojo_Toolkit_with_the_Closure_Compiler.pdf?by-user=t

Ответ 5

Хотя это старый вопрос. Я наткнулся на ту же проблему сегодня и обнаружил, что ее можно достичь, используя 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... и т.д.

Ответ 6

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

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

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

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

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

Ответ 7

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

Ответ 8

Я с @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");

Ответ 9

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

s/;;;.*//g

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

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

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

Ответ 10

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

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

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

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