Google Closure Compiler - удаление мертвого кода на основе внешних

Я пытаюсь использовать компилятор закрытия Google, чтобы разделить код моего приложения в зависимости от того, где он будет запускаться (на сервере или на клиенте) с помощью одной переменной. В этом примере все, что будет вызываться на сервере, находится за переменной isServerSide, НО код компилируется для клиента. Поэтому я установлю для isServerSide значение false и позволю компилятору удалить все, что не будет запускаться клиентом...

Внутри app.js:

goog.provide('my.app');
my.app.log = function(message) {
  document.write(message);
}
my.app.initClientSide = function() {
  my.app.log('hello client');
}

my.app.initServerSide = function() {
  my.app.log('hello server');
}

if (isServerSide) {
  my.app.log('initing server');
  my.app.initServerSide()
}else my.app.initClientSide();

Внутри externs.js:

/**
 * @define {boolean} is server side?
 */
var isServerSide=false;

Команда:

java -jar bin/compiler.jar --js closure-library/closure/goog/base.js --js app.js --externs externs.js --manage_closure_dependencies true --process_closure_primitives true --summary_detail_level 3 --warning_level VERBOSE --compilation_level=ADVANCED_OPTIMIZATIONS --closure_entry_point my.app

Ожидаемый результат:

document.write("hello client");

Фактический результат:

isServerSide?(document.write("initing server"),document.write("hello server")):document.write("hello client");

Если я вручную наберу isServerSide=false; в app.js, тогда я смогу скомпилировать его следующим образом:

isServerSide=false;document.write("hello client");

Это заставляет меня думать, что я неправильно настраиваю свой externs.js (или я просто не понимаю, для чего на самом деле должны использоваться внешние).

Любые предложения о том, как заставить это работать?


person Lite Byte    schedule 09.11.2011    source источник
comment
Экстерны предназначены для резервирования внешних имен и определения сигнатур функций/типов (например, jQuery), поэтому я не думаю, что компилятор обращает внимание на их значения. Можно ли разделить app.js на app_client.js и app_server.js, чтобы код клиент/сервер всегда вызывал соответствующие версии?   -  person hyperslug    schedule 09.11.2011
comment
Как говорит @hyperslug, внешние элементы должны указывать компилятору, что переменная определена во внешнем сценарии. Компилятор ИГНОРИРУЕТ ЕГО ЗНАЧЕНИЕ, предполагая, что переменная будет установлена ​​этим внешним сценарием. Таким образом, вы можете видеть, что компилятор не удаляет ни одну из двух ветвей в операторе if, потому что он не знает, каково значение этой переменной extern. Что вам нужно, так это @define в вашем скрипте, а затем используйте переключатель компилятора --define, чтобы включить/выключить его. В этом случае вы получите ожидаемый результат.   -  person Stephen Chung    schedule 09.11.2011
comment
Спасибо, парни. Просто чтобы подтвердить, что то, что вы оба сказали, было абсолютно правильно :)   -  person Lite Byte    schedule 13.11.2011
comment
Просто для ясности вам нужно добавить /** @define {boolean} */ isServerSide=false; каждому сценарию, которому требуется значение isServerSide?   -  person pgraham    schedule 07.03.2014


Ответы (1)


Вы указываете значения @define, устанавливая их непосредственно в вызове компилятора. Экстерны служат другой цели, как правильно заявляет гиперслаг.

Вы достигаете ожидаемого результата, помещая определение @define (из вашего внешнего модуля) в app.js, а затем вызывая компилятор следующим образом:

java -jar compiler.jar \
--define "isServerSide=false" \
--js closure-library/closure/goog/base.js \
--js app.js \
--manage_closure_dependencies true \
--process_closure_primitives true \
--summary_detail_level 3 \
--warning_level VERBOSE \
--compilation_level=ADVANCED_OPTIMIZATIONS \
--closure_entry_point my.app
person Carsten    schedule 09.11.2011
comment
Спасибо, это сработало. Если кому интересно, я создал новый файл (isServerSide.js) и goog.require вставил его в my.app. Таким образом, я не загромождаю код приложения операторами определения, но я могу установить define в cmd компилятора... - person Lite Byte; 13.11.2011