Использовать функции журнала ловушки компилятора Closure
У меня есть API протоколирования, который я хочу открыть для некоторого внутреннего JS-кода. Я хочу иметь возможность использовать этот API для регистрации, но только тогда, когда я делаю сборку отладки. Сейчас я частично работаю. Он регистрируется только на отладочных сборках, но вызовы этого API все еще находятся в коде при регулярной сборке. Я хотел бы, чтобы компилятор-замыкатель удалял этот по существу мертвый код, когда компилятор с goog.DEBUG = false.
Определение журнала:
goog.provide('com.foo.android.Log');
com.foo.Log.e = function(message){
goog.DEBUG && AndroidLog.e(message);
}
goog.export(com.foo.Log, "e", com.foo.Log.e);
AndroidLog - это объект Java, предоставляемый веб-просмотру, который будет запущен и правильно выведен следующим образом:
var AndroidLog = {};
/**
* Log out to the error console
*
* @param {string} message The message to log
*/
AndroidLog.e = function(message) {};
Затем в моем коде я могу использовать:
com.foo.Log.e("Hello!"); // I want these stripped in production builds
Мой вопрос заключается в следующем: как я могу предоставить этот API, использовать этот API по всему моему коду, но затем удалить любые вызовы этого API, если они не скомпилированы с goog.DEBUG = true? Прямо сейчас, моя база кода раздувается с кучей вызовов в Log API, которые никогда не вызываются. Я хочу удалить.
Спасибо!
Ответы
Ответ 1
ОК, получается, что это легко сделать, если я прекращаю экспорт com.foo.Log() и его методов. Если я действительно хочу иметь возможность регистрироваться в некоторых конкретных случаях, но все равно изгоняю вызовы журнала во внутреннем коде, я могу просто объявить для этого два класса:
// This will get inlined and stripped, since its not exported.
goog.provide('com.foo.android.Log');
com.foo.Log.e = function(message){
goog.DEBUG && AndroidLog.e(message);
}
// Don't export.
// This be available to use after closure compiler runs, since it exported.
goog.provide('com.foo.android.production.Log');
goog.exportSymbol("ProductionLog", com.foo.android.production.Log);
com.foo.android.production.Log.log = function(message){
goog.DEBUG && AndroidLog.e(message);
}
// Export.
goog.exportProperty(com.foo.android.production.Log, "log", com.foo.android.production.Log.log);
Ответ 2
Компилятор Closure предоставляет четыре опции в CompilerOptions.java для разметки кода: 1) stripTypes
, 2) stripNameSuffixes
, 3) stripNamePrefixes
и 4) stripTypePrefixes
. Инструмент сборки Closure plovr предоставляет stripNameSuffixes
и stripTypePrefixes
через его конфигурационные параметры JSON name-suffixes-to-strip
и type-prefixes-to-strip
.
Есть отличные примеры того, как эти параметры работают в Closure: Полное руководство на страницах с 442 по 444. В качестве общих случаев используются следующие строки:
options.stripTypePrefixes = ImmutableSet.of("goog.debug", "goog.asserts");
options.stripNameSuffixes = ImmutableSet.of("logger", "logger_");
Чтобы понять нюансы этих параметров и избежать потенциальных ошибок, я настоятельно рекомендую прочитать полные примеры в "Закрытии: окончательное руководство".
Ответ 3
Вместо того, чтобы запускать свой собственный script, как предлагал jfriend00, я бы посмотрел на определение api компилятора (с которого также появляется goog.DEBUG), у вас есть DEBUG, COMPILED по умолчанию, но там вы можете перевернуть ваш собственный.
Ответ 4
Я изменил компилятор и упаковал его как пакет npm.
Вы можете получить его здесь: https://github.com/thanpolas/superstartup-closure-compiler#readme
Он будет разбивать все сообщения журнала во время компиляции