这里就是我在寻找:有没有办法告诉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”添加到我的问题中,作为对您问题的回复。事实上,如果您阅读了我原来的问题,那么您可能会考虑“可能重复”的意见。和平兄弟。 –