這裏就是我在尋找:有沒有辦法告訴Google Closure Compiler *不*內聯我的本地功能?
- 我想同時禁用只是一個特定功能(禁用本地內聯函數)使用簡單模式微小的奇妙的功能。
- UPDATE:答案是NO,它給我的設置是不可能的。但是對於我來說有一個解決方法,因爲我正在使用Grails。
- 正如@Chad在下面解釋的那樣,「這違反了編譯器的核心假設」。有關更多信息,請參閱下面的UPDATE3。
在問表:
- 我使用
CompilationLevel.SIMPLE_OPTIMIZATIONS
該做的一切我想要的,只不過它內聯我的本地功能。 - 有沒有辦法解決這個問題?例如,是否可以在我的JS文件中放置一個設置來告訴Google Closure不要內聯我的本地功能?
這將是很酷的,在我的javascript文件的頂部,如一些指令:
// This is a JS comment...
// google.closure.compiler = [inlineLocalFunctions: false]
我開發一個Grails應用程序,並使用Grails asset-pipeline插件,它使用谷歌關閉編譯器(此後,編譯器)。該插件支持編譯器通過Grails config grails.assets.minifyOptions支持的不同縮小級別。這允許'簡單','高級','WHITESPACE_ONLY'。
AssetCompiler.groovy(資產流水線插件)調用ClosureCompilerProcessor.process()
,最終分配SIMPLE_OPTIMIZATIONS
在CompilerOptions對象。通過這樣做,CompilerOptions.inlineLocalFunctions = true
作爲副產品(這是編譯器中的硬編碼行爲)。如果我要使用WHITESPACE_ONLY
,結果將是inlineLocalFunctions=false
。
因此,通過使用Asset Pipeline的'SIMPLE'設置,本地函數正在被內聯,這給我帶來了麻煩。例如:ExtJS ext-all-debug.js,它使用許多本地功能。
SO帖子Is it possible to make Google Closure compiler *not* inline certain functions?提供了一些幫助。我可以使用它的window['dontBlowMeAway'] = dontBlowMeAway
技巧來保持我的函數不被內聯。不過,我有很多功能,我不打算爲每個功能手動執行此操作;我也不想寫一個腳本來爲我做。創建JS模型並嘗試識別本地函數聽起來並不安全,有趣也不快。
之前的SO帖子指示讀者到https://developers.google.com/closure/compiler/docs/api-tutorial3#removal,其中window['bla']
技巧被解釋,它的工作原理。
感謝您閱讀這篇長文。
幫助? :-)
UPDATE1:
好。在花費所有的精力寫這個問題的時候,我可能會有一個可行的竅門。 Grails使用Groovy。 Groovy使用它的MetaClass API使方法調用攔截變得容易。
我要去嘗試呼叫攔截到:
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: 在一個類似的帖子(Is it possible to make Google Closure compiler *not* inline certain functions?)的響應不能解決,因爲我需要內聯函數的大量的我的問題。我已經解釋了這一點。
以上面引用的ExtJS文件爲例說明爲什麼上述similar SO post無法解決我的問題。看看ext-all-debug.js的原始代碼。找到byAttribute()函數。然後繼續查找字符串「byAttribute」,你會發現它是正在定義的字符串的一部分。我對此代碼並不熟悉,但我認爲byAttribute
的這些基於字符串的值稍後將傳遞給JS's eval()函數以供執行。當它是字符串的一部分時,編譯器不會更改byAttribute
的這些值。一旦function byAttribute
內聯,嘗試調用該函數不再可能。
UPDATE3:我嘗試兩種策略來解決這個問題,都證明是不成功的。但是,我成功實施了一種解決方法。我的失敗嘗試:
- 使用Groovy方法攔截(元對象協議,又稱MOP)攔截
com.google.javascript.jscomp.Compiler.compile()
。 - 分叉closure-compiler.jar(製作我自己的自定義副本)並通過設置
options.setInlineFunctions(Reach.NONE);
而不是LOCAL修改com.google.javascript.jscomp.applySafeCompilationOptions()
。
方法攔截不起作用,因爲Compiler.compile()
是由Groovy類調用的Java類,標記爲@CompileStatic
。這意味着當process()
稱爲Google的Compiler.compile()
時,Groovy的MOP不會被使用。即使ClosureCompilerProcessor.translateMinifyOptions()
(Groovy代碼)也不能被攔截,因爲該類是@CompileStatic
。唯一可以攔截的方法是ClosureCompilerProcessor.process()
。
分叉Google的closure-compiler.jar是我最後一個醜陋的手段。但就像下面的@Chad所說的那樣,只要在正確的位置插入options.setInlineFunctions(Reach.NONE)
就不會重新生成我的內聯JS函數名稱。我試圖切換其他選項,如setRemoveDeadCode=false
無濟於事。我意識到乍得說的是對的。我最終會翻轉設置並可能破壞縮小的工作方式。
我的解決方案:我用UglifyJS預壓縮了ext-all-debug.js並將它們添加到我的項目中。我可以命名文件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
你能解釋**爲什麼**本地函數內聯會導致你的問題?有多種技術可以防止這種情況,但我需要知道提出建議的核心原因。 –
[可以使Google Closure編譯器\ *不是\ *內聯某些函數嗎?]的可能的重複?(http://stackoverflow.com/questions/4297685/is-it-possible-to-make-google-closure-編譯器非內聯特定函數) –
謝謝@ChadKillingsworth。我已將「UPDATE2」添加到我的問題中,作爲對您問題的回覆。事實上,如果您閱讀了我原來的問題,那麼您可能會考慮「可能重複」的意見。和平兄弟。 –