Есть ли способ сообщить компилятору Google Closure * НЕ * встроить мои локальные функции?

Вот что я ищу:

Я хочу использовать замечательные функции минимизации режима SIMPLE при отключении только одной конкретной функции (отключить локальную функцию inline).


ОБНОВЛЕНИЕ: ответ НЕТ, это невозможно, учитывая мои настройки. Но для меня есть обходной путь, учитывая, что я использую Grails.Как объясняет @Chad ниже: «Это нарушает основные предположения компилятора». Смотрите мою UPDATE3 ниже для получения дополнительной информации.


В ФОРМЕ ВОПРОСА:

я используюCompilationLevel.SIMPLE_OPTIMIZATIONS который делает все, что я хочу, за исключением того, что он встроен в мои локальные функции.Есть ли способ обойти это? Например, есть ли параметр, который я могу разместить в моих файлах JS, чтобы запретить Google Closure встроенным функциям?

Было бы здорово иметь некоторые директивы в верхней части моего файла JavaScript, такие как:

// This is a JS comment...
// google.closure.compiler = [inlineLocalFunctions: false]

Я разрабатываю приложение Grails и используюGrails актив-трубопровод плагин, который использует Google Closure Compiler (далее «Компилятор»). Плагин поддерживает различные уровни минимизации, которые компилятор поддерживает через конфигурацию Grailsgrails.assets.minifyOptions, Это позволяет использовать «SIMPLE», «ADVANCED», «WHITESPACE_ONLY».

AssetCompiler.groovy (плагин актив-конвейер) вызываетClosureCompilerProcessor.process()

Это в конечном итоге назначаетSIMPLE_OPTIMIZATIONS на объекте CompilerOptions. И тем самым,CompilerOptions.inlineLocalFunctions = true как побочный продукт (это жестко запрограммированное поведение в компиляторе). Если бы я должен был использоватьWHITESPACE_ONLY результат будетinlineLocalFunctions=false.

Таким образом, используя настройку «ПРОСТО» в Asset Pipeline, локальные функции встроены, и это вызывает у меня проблемы. Пример: ExtJSдоб-все-debug.js который использует множество локальных функций.

ТАК сообщениеМожно ли сделать компилятор Google Closure * не * встроенным в определенные функции? предоставляет некоторую помощь. Я могу использовать егоwindow['dontBlowMeAway'] = dontBlowMeAway трюк, чтобы мои функции не были встроены. Однако у меня много функций, и я не собираюсь делать это вручную для каждой из них; и при этом я не хотел бы написать сценарий, чтобы сделать это для меня. Создание модели JS и попытка идентифицировать локальные функции не звучат ни безопасно, ни весело, ни быстро.

Предыдущий пост SO направляет читателя кhttps://developers.google.com/closure/compiler/docs/api-tutorial3#removal, гдеwindow['bla'] хитрость объясняется, и это работает.

Вау, спасибо, что прочитал это долго.

Помогите? :-)

Update1:

Хорошо. Затрачивая все усилия на написание этого вопроса, у меня может быть хитрость, которая может сработать. Grails использует Groovy. Groovy упрощает перехват вызовов методов с помощью API MetaClass.

Я собираюсь попытаться перехватить вызов:

com.google.javascript.jscomp.Compiler.compile(
    List<T1> externs, List<T2> inputs, CompilerOptions options)

Мой метод перехвата будет выглядеть так:

options.inlineLocalFunctions=false
// Then delegate call to the real compile() method

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


UPDATE2: Ответ в аналогичном посте (Можно ли сделать компилятор Google Closure * не * встроенным в определенные функции?) не решает мою проблему из-за большого количества функций, которые мне нужны. Я уже объяснил этот момент.

Возьмите файл ExtJS, который я цитировал выше, в качестве примера того, почемуаналогичный пост SO не решает мою проблему. Посмотрите на сырой код длядоб-все-debug.js, Найдите функцию byAttribute (). Затем продолжайте искать строку «byAttribute», и вы увидите, что она является частью определяемой строки. Я не знаком с этим кодом, но я предполагаю, что эти строковые значенияbyAttribute позже передаютсяJS Eval () функция для исполнения. Компилятор не изменяет эти значенияbyAttribute когда это часть строки. однаждыfunction byAttribute попытка вызова функции больше невозможна.


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

Используйте метод перехвата Groovy (Meta Object Protocol, также известный как MOP) для перехватаcom.google.javascript.jscomp.Compiler.compile().Разверните файл closure-compiler.jar (сделайте свою собственную копию) и изменитеcom.google.javascript.jscomp.applySafeCompilationOptions() установивoptions.setInlineFunctions(Reach.NONE); вместо МЕСТНОГО.

Перехват метода не работает, потому чтоCompiler.compile() класс Java, который вызывается классом Groovy, помеченным как@CompileStatic, Это означает, что Groovy MOP не используется, когдаprocess() звонит GoogleCompiler.compile(), ЧетноеClosureCompilerProcessor.translateMinifyOptions() (Groovy код) не может быть перехвачен, потому что класс@CompileStatic, Единственный метод, который можно перехватить, этоClosureCompilerProcessor.process().

Форкинг Google closure-compiler.jar был моим последним уродливым средством. Но, как сказал @Chad ниже, просто вставивoptions.setInlineFunctions(Reach.NONE) в нужном месте не воскресил мои встроенные имена функций JS. Я пытался переключить другие варианты, такие какsetRemoveDeadCode=false но безрезультатно. Я понял, что Чад сказал правильно. Я бы в конечном итоге перевернул настройки и, вероятно, разрушил бы работу минификации.

Мое решение: Я предварительно сжал ext-all-debug.js с помощью UglifyJS и добавил их в свой проект. Я мог бы назвать файлыext-all-debug.min.js сделать это более аккуратно, но я не сделал. Ниже приведены настройки, которые я разместил в своем Grails Config.groovy:

grails.assets.minifyOptions = [
    optimizationLevel: 'SIMPLE' // WHITESPACE_ONLY, SIMPLE or ADVANCED
]

grails.assets.minifyOptions.excludes = [
    '**ext-all-debug.js',
    '**ext-theme-neptune.js'
]

Готово. Задача решена.




Ключевые слова: минификация, минификация, углификация, UglifyJS, UglifyJS2

Ответы на вопрос(2)

Ваш ответ на вопрос