2012-05-03 10 views
2

私は最近Google Closure Compilerをチェックアウトしています。私は.jarファイルをダウンロードし、テストドライブを与えました。これまでのところ、私は非常に感銘を受けたと言わなければなりません。私は最小限を超えてその有用性を確かに見ることができます。 Googleチームの小道具!GoogleクローズコンパイラのADVANCED_OPTIMIZATIONSオプション

私は1つの小さなグリップを持っています。最適化が行われる限り、2つの選択肢しか得られないようです。 SIMPLE_OPTIMIZATIONSまたはADVANCED_OPTIMIZATIONSのいずれかです。前者は、適切ではあるが、非常に単純なIMHOです。一つは、私が何かを逃していない限り、それはすべてのプロパティの名前を手つかずのままにします。到達不能なコードは削除されません。一方、後者の選択肢は単に破壊的すぎる。

今、私はJavaScriptをかなり新しくしているので、何かが欠けている可能性が非常に高いです。私が何か愚かなことを言うならば、学校に私を自由に感じてください。つまり、私はJavaScriptで名前を変更することで問題を理解することができます。 Googleチームは、ドット表記(object.property)ではなくブラケット表記(オブジェクト['property'])を使用して、変更したくないプロパティにアクセスし、2つの用途を混同しないようにすることをお勧めします。ただし、次の2つの表記をミックスしたい正当な場合がある

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

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

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

:彼らはまた、次のパターンを使用して、「エクスポート」方法を提案します。私たちがゲームを作っているとしよう。ゲームのコードはクロージャ内で完全に分離されています。それは、グローバルスコープに何もエクスポートしたり、それを必要としません。実際には、実際にはウィンドウオブジェクトに触れてはいけません。ただし、の場合、は、XML設定ファイルからゲーム内のプロパティを読み取る必要があります。

サンプルの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)); 

サンプルXML設定ファイル:上記のシステムプロパティを割り当てることができないでしょう

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

だけでなく、機能cassieAttackとcassieSpeakはとして最小化中に除去されていたであろうデッドコード!

ここでは、ゲームのコード全体でブラケット表記を使用して、すべての「公開済み」プロパティにアクセスする方法はありません。そうすることで実行時のペナルティがなくても(何もすべきではない)、余分なタイピングがまだたくさんあり、それは目障りです(IMO)。このような共通のプロパティを使用すると、すべてがシンタックスハイライトの目的を破ってテキストエディタ内に文字列として表示されます。

これらのプロパティよりも単純な@preserve(またはそれに類するもの)ディレクティブを使用すると、ADVANCED_OPTIMIZATIONSを最終的なプログラムサイズで最小限のコストで使用できるようになります。何か不足していますか?

+0

私は同様の質問に対する回答があります:http://stackoverflow.com/questions/7823811/prevent-google-closure-compiler-from-renaming-settings-objects/7834912#7834912 –

答えて

3

この回答は完全に書き直され、user1127813が望むことを行う方法があることが判明しました。

--property_map_input_fileフラグを使用して、いくつかの名前をマップするプロパティマッピングファイルを提供する必要があります。

/** @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]); 
} 

ので、同じようにそれをコンパイルします:あなたはtest.jsで、次の元のコードがあるとし

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

あなたは(動作しない内容で)新しいファイルtest2.jsを取得し、別のファイルtestprop.txtこと含まれています

ID:a 
hitPoints:c 
fullName:b 

変更testprop.txtので、それはこのようになりますそして

ID:ID 
hitPoints:hitPoints 
fullName:fullName 

代わり出力の入力として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 

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]); 

所望の特性は、現在のドット表記法を使用して、元の名前でアクセスされていますプログラムは正しくbobの公開プロパティでポップアップを表示します。

+0

まずは、ありがとうございます。しかし、コンパイラの名前変更モジュールに、識別子の小さなリストだけを残すように指示すると、プログラム全体(すべての40K行)に括弧表記を使用するよりも好ましいと思われませんか?さらに、/あなたが別のミニマイザを使用することを決定したときにはどうなりますか?あなたは括弧内の文字列で立ち往生しています。これは、副作用を誘発する(つまり、コンパイラに特定の変数だけを残させる)ために、あなたがしてはいけないもの(プログラムのコード)を変更するケースです。 – user1127813

+0

上記の例では、アプリケーションのユーザーによってXMLファイルが提供されるため、プロパティマップの使用についてはわかりません(私はそれを明確にしていないと思います)。 – user1127813

+0

あなたはその機能について正しくあります。もちろん、オブジェクトのメソッドでなければなりません(readFromXMLNode()のbindContext変数で表されます)。 – user1127813

3

コンパイラは、このためのサポートを持っていますが、それは厄介で、かつ閉鎖ライブラリから「原始的」に依存しますが、「goog.reflect.object」と呼ばれる:

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

これは引用されたプロパティの使用を避けます。これがクロージャライブラリから使用する唯一のものであれば、 "goog.object.transpose"関数はコンパイルされます(goog.object.transposeは特別なものではなく、別の実装を自由に使用できます)。これは型安全であり、コンパイラの型に基づく最適化で使用することができます(ここでの説明はhttp://code.google.com/p/closure-compiler/wiki/ExperimentalTypeBasedPropertyRenamingを参照してください)。

キーはgoog.reflect.objectをコンストラクタとオブジェクトリテラルを保持する必要があるプロパティのキーで直接使用する必要があるということです。

ADVANCEDモードでFighter.publishedPropertiesがグローバルスコープで定義されている場合、ネームスペースが崩壊するため、これはコンストラクタから削除されます。 @nocollapseはこれを防ぎます。代替プロパティを追加するヘル​​パーメソッドを使用することです:

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

[OK]を、私はあなたが明確化したいなら、私に知らせてください、ここで地上の多くをカバーしてきました。

関連する問題