简体   繁体   English

Google Closure编译器的ADVANCED_OPTIMIZATIONS选项

[英]Google Closure Compiler's ADVANCED_OPTIMIZATIONS option

I've been checking out the Google Closure Compiler recently. 我最近一直在检查Google Closure Compiler。 I downloaded the .jar file and gave it a test drive. 我下载了.jar文件,并对其进行了测试。 So far, I must say that I've been very impressed. 到目前为止,我必须说,我印象深刻。 I can certainly see its usefulness beyond minimization. 我当然可以看到它的作用不仅限于最小化。 Props to the Google team! 向Google团队提供支持!

I do have one small gripe though. 我确实有一个小抱怨。 It seems to me that you only get two options as far as optimization goes. 在我看来,就优化而言,您只有两种选择。 It's either SIMPLE_OPTIMIZATIONS or ADVANCED_OPTIMIZATIONS. 它是SIMPLE_OPTIMIZATIONS或ADVANCED_OPTIMIZATIONS。 The former, although adequate, is very simple IMHO. 前者虽然足够,但非常简单,恕我直言。 For one thing, unless I'm missing something, it leaves all property names untouched. 一方面,除非我缺少任何内容,否则所有属性名称都保持不变。 It also does not remove unreachable code. 它还不会删除无法访问的代码。 On the other hand, the latter option is simply too destructive. 另一方面,后一种选择太具有破坏性。

Now, I'm fairly new to JavaScript, so it's very probable that I'm missing something. 现在,我对JavaScript还是很陌生,所以很可能我遗漏了一些东西。 If I say something stupid, feel free to school me. 如果我说些蠢话,请随时向我求学。 That said, I can understand the issues with renaming in JavaScript. 也就是说,我可以理解JavaScript重命名的问题。 The Google team recommends using the bracket notation (object['property']) instead of the dot notation (object.property) to access the properties that you do not want changed and never mixing the two uses. Google小组建议使用方括号(object ['property'])而不是点号(object.property)来访问您不想更改的属性,并且永远不要将这两种用法混合使用。 They also suggest 'exporting' methods by using the following pattern: 他们还建议使用以下模式进行“导出”方法:

MyClass = function(name) {
  this.myName = name;
};

MyClass.prototype.myMethod = function() {
  alert(this.myName);
};

window['MyClass'] = MyClass; // <-- Constructor
MyClass.prototype['myMethod'] = MyClass.prototype.myMethod;

However, there are legitimate cases that you want to mix the two notations. 但是,在某些合理的情况下,您需要将两种表示法混合使用。 Let's say we are building a game. 假设我们正在开发游戏。 The game's code is completely isolated inside a closure. 游戏的代码完全封闭在封闭中。 It does not 'export' anything to the global scope, nor does it need to. 它不会“出口”任何东西到全球范围,也不需要。 In fact, it really should not touch the window object. 实际上,它确实不应该触摸窗口对象。 However, it does need to read some in-game properties from XML configuration files. 但是,它确实需要从XML配置文件中读取一些游戏内属性。

Sample JavaScript: 示例JavaScript:

var TheGreatAdventure = (function(window) {

    function Fighter() {
        // Private to application
        this.id        = 42;
        // Accessible to XML configuration system
        this.name      = 'Generic Jen';
        this.hitPoints = 100;
        this.onAttack  = genericFighterAttack;
        this.onSpeak   = genericFighterSpeak;
        ...
    }
    Fighter.publishedProperties = ['name', 'hitPoints', 'onAttack', 'onSpeak']

    function genericFighterAttack() {...}
    function genericFighterSpeak() {...}

    function cassieAttack() {...}
    function cassieSpeak() {...}

    ...

    EntityReader = {
        ...
        function readFromXMLNode(attributes, entityClass, entityInstance) {
            for (var i = 0; i < attributes.length; i++) {
                var attribute = attributes[i];
                if (attribute.nodeName in entityClass.publishedProperties)
                    entityInstance[attribute.nodeName] = bindContext[attribute.value];
            }
        }
        ...
    }

}(window));

Sample XML configuration file: XML配置文件样本:

<Fighter name='Custom Cassie' onAttack='cassieAttack' onSpeak='cassieSpeak'/>

Not only would the above system fail to assign the properties, the functions cassieAttack and cassieSpeak would have been eliminated during minimization as dead code! 不仅上述系统无法分配属性,而且在最小化过程中已将cassieAttack和cassieSpeak函数取消为死代码!

Now, there's no way I'm accessing all of the 'published' properties using the bracket notation throughout the game's code. 现在,我无法使用整个游戏代码中的括号符号来访问所有“已发布”属性。 Even if there's no run-time penalty in doing so (there should not be any), there's still a lot of extra typing involved and it's (IMO) an eyesore. 即使这样做没有运行时间的损失(不应该有任何损失),仍然涉及很多额外的类型输入,这很令人讨厌。 With such common properties, everything would show up as a string inside a text editor, defeating the purpose of syntax highlighting! 有了这样的通用属性,所有内容都将在文本编辑器中显示为字符串,从而破坏了语法高亮的目的!

It seems to me that a simple @preserve (or something similar) directive over those properties would allow ADVANCED_OPTIMIZATIONS to be used with minimum cost in final program size. 在我看来,对这些属性使用简单的@preserve(或类似的指令)指令将允许以最低的最终程序大小成本使用ADVANCED_OPTIMIZATIONS。 Am I missing something? 我想念什么吗?

This answer was completely rewritten, turns out there's a way to do what user1127813 wants. 答案已被完全重写,原来有一种方法可以执行user1127813想要的操作。

You need to provide a property mapping file that maps some names to themselves, using the --property_map_input_file flag. 您需要提供一个属性映射文件,该文件使用--property_map_input_file标志将一些名称映射到自身。 Suppose you have the following original code in test.js : 假设您在test.js具有以下原始代码:

/** @constructor */
function Fighter() {
    this.ID        = 42;
    this.fullName  = 'Generic Jen';
    this.hitPoints = 100;
}
Fighter.publishedProperties = ['fullName', 'hitPoints'];

var jen = new Fighter();
var bob = new Fighter();

bob.ID = 54;
bob.fullName = 'Bob the Destructor';
bob.hitPoints = 1337;

for(i = 0; i < Fighter.publishedProperties.length; i++) {
    prop = Fighter.publishedProperties[i];
    alert(prop + ' = ' + bob[prop]);
}

Compile it like so: 像这样编译它:

java -jar closure-compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js test.js --property_map_output_file testprop.txt --js_output_file test2.js

You will get a new file test2.js (with contents that don't work) and another file testprop.txt that contains: 您将获得一个新文件test2.js (其内容无效)和另一个文件testprop.txt ,其中包含:

ID:a
hitPoints:c
fullName:b

Change testprop.txt so it looks like this: 更改testprop.txt ,使其如下所示:

ID:ID
hitPoints:hitPoints
fullName:fullName

Then recompile with testprop.txt as input instead of output: 然后使用testprop.txt作为输入而不是输出重新编译:

java -jar closure-compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js test.js --property_map_input_file testprop.txt --js_output_file test2.js

Observe the contents of test2.js : 观察test2.js的内容:

var a=["fullName","hitPoints"],b=new function(){};b.ID=54;b.fullName="Bob the Destructor";b.hitPoints=1337;for(i=0;i<a.length;i++)prop=a[i],alert(prop+" = "+b[prop]);

The desired properties are now accessed with their original name using the dot notation and the program will correctly show popups with the published properties of bob. 现在,使用点符号以其原始名称访问所需的属性,程序将正确显示带有bob发布的属性的弹出窗口。

The compiler has support for this, but it is awkward, and depends on a "primitive" from the Closure Library called "goog.reflect.object": 编译器对此有支持,但是很尴尬,它依赖于Closure库中名为“ goog.reflect.object”的“原始”:

/** @nocollapse */
Fighter.publishedProperties = goog.object.transpose(goog.reflect.object(
    Fighter, {fullName:1, hitPoints:2}));

This avoid the use of quoted properties. 这样可以避免使用带引号的属性。 If this is the only thing that you use from the Closure Library everything but the "goog.object.transpose" function will be compiled out (goog.object.transpose isn't special so you are free to use an alternate implementation). 如果这是从Closure库中唯一使用的东西,那么除“ goog.object.transpose”功能外的所有内容都将被编译出来(goog.object.transpose并不特殊,因此您可以自由使用替代实现)。 This is type safe and can be used with the compiler's type based optimizations (see a discription of that here: http://code.google.com/p/closure-compiler/wiki/ExperimentalTypeBasedPropertyRenaming ). 这是类型安全的,可以与编译器的基于类型的优化一起使用(请在此处查看其说明: http : //code.google.com/p/closure-compiler/wiki/ExperimentalTypeBasedPropertyRenaming )。

The key is that goog.reflect.object must be used directly, taking the constructor and an object literal with the keys of the properties you need to preserve. 关键是goog.reflect.object必须直接使用,并使用构造函数和带有要保留的属性的键的对象文字。

The other thing that you will want to be aware of this that in ADVANCED mode, if Fighter.publishedProperties is defined in global scope, it will be removed from the constructor due to namespace collapsing. 您还需要注意的另一件事是,在ADVANCED模式下,如果Fighter.publishedProperties是在全局范围内定义的,则由于命名空间崩溃而将其从构造函数中删除。 @nocollapse prevents this. @nocollapse可以防止这种情况。 An alternative would be to use a helper method to add the property: 一种替代方法是使用辅助方法添加属性:

function addPublishedProperties(obj, value) {
  obj.publishedProperties = goog.object.transpose(value);
}

Ok, I've covered a lot of ground here so be sure to let me know if you would like clarification. 好的,我在这里已经介绍了很多内容,因此如果您需要澄清,请务必让我知道。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Google Closure Compiler ADVANCED_OPTIMIZATIONS - 排除所有函数名称 - Google Closure Compiler ADVANCED_OPTIMIZATIONS - Exclude All function names 具有Closure Compiler和ADVANCED_OPTIMIZATIONS的模块模式 - Module pattern with Closure Compiler and ADVANCED_OPTIMIZATIONS 使用闭包编译器 ADVANCED_OPTIMIZATIONS 的奇怪对象属性行为 - strange object property behavior with closure compiler ADVANCED_OPTIMIZATIONS 是否可以使用闭包编译器ADVANCED_OPTIMIZATIONS与jQuery? - Is it possible to use Closure Compiler ADVANCED_OPTIMIZATIONS with jQuery? 如何在ADVANCED_OPTIMIZATIONS中的Closure Compiler中导出公共类方法? - How to export public class methods in Closure Compiler in ADVANCED_OPTIMIZATIONS? 如何不编译goog.closure中的某些代码ADVANCED_OPTIMIZATIONS - How to not compile certain code in goog.closure ADVANCED_OPTIMIZATIONS 关闭编译ADVANCED_OPTIMIZATIONS抱怨使用此方法 - closure compilation ADVANCED_OPTIMIZATIONS complaining about use of this 具有高级优化和外部功能的Closure编译器 - Closure Compiler with Advanced Optimizations and Externs 闭包编译器,缺少具有高级优化功能的方法? - Closure Compiler, missing method with advanced optimizations? 是否可以避免使用带有getter和setter的模式,而仍然使用Closure ADVANCED_OPTIMIZATIONS最小化JavaScript? - Can a pattern with getters and setters be avoided and still minify JavaScript with Closure ADVANCED_OPTIMIZATIONS?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM