Есть ли способ сообщить компилятору Google Closure * НЕ * встроить мои локальные функции?
Вот что я ищу:
Я хочу использовать замечательные функции минимизации режима SIMPLE при отключении только одной конкретной функции (отключить локальную функцию inline).В ФОРМЕ ВОПРОСА:
я использую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