以下是我要找的内容:
问题形式:
CompilationLevel.SIMPLE_OPTIMIZATIONS
来完成我想要的一切,除了它内联我的本地功能。在我的javascript文件的顶部有一些指令很酷,例如:
// This is a JS comment...
// google.closure.compiler = [inlineLocalFunctions: false]
我正在开发Grails应用并使用Grails asset-pipeline插件,该插件使用Google Closure Compiler(以下称为编译器)。该插件通过Grails config grails.assets.minifyOptions支持Compiler支持的不同缩小级别。这样就可以实现“简单”,“高级”,“白痴”等。
AssetCompiler.groovy(asset-pipeline plugin)调用ClosureCompilerProcessor.process()
最终在CompilerOptions对象上分配SIMPLE_OPTIMIZATIONS
。通过这样做,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()函数。然后继续寻找字符串&#34; byAttribute&#34;并且您将看到它是正在定义的字符串的一部分。我不熟悉这段代码,但我假设这些基于字符串的byAttribute
值稍后被传递给JS's eval()函数执行。当编译器成为字符串的一部分时,编译器不会更改byAttribute
的这些值。内联function byAttribute
后,无法再尝试调用该函数。
UPDATE3:我尝试了两种解决此问题的策略,但都证明不成功。但是,我成功实施了一种解决方法。我尝试失败了:
com.google.javascript.jscomp.Compiler.compile()
。com.google.javascript.jscomp.applySafeCompilationOptions()
而不是LOCAL来修改options.setInlineFunctions(Reach.NONE);
。方法拦截不起作用,因为Compiler.compile()
是一个Java类,由标记为@CompileStatic
的Groovy类调用。这意味着当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'
]
完成。问题解决了。
关键词:minify,minification,uglify,UglifyJS,UglifyJS2
答案 0 :(得分:2)
在这种情况下,您需要自定义构建编译器或使用Java API。
然而 - 禁用内联不足以使其安全。重命名和死代码消除也会导致问题。这违反了编译器的核心假设。此本地函数仅在字符串中引用。
此代码仅对编译器的WHITESPACE_ONLY
模式安全。
答案 1 :(得分:0)
使用函数构造函数
Subform1
Closure将保留String文字。
请参阅https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Function