4

我使用Typescript命令(tsc)創建一個包含所有平板類的單個Javascript文件。Typescript和Google Closure

tsc "./Main.ts" -out "./script/myProject_debug.js" --declarations 

然後,我想混淆與谷歌閉幕(compiler.jar)這樣的文件:

java -jar ./compiler/compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js "./script/myProject_debug.js" > "./script/myProject.js". 

但是,當我執行結果混淆/優化的代碼,我得到這個以下錯誤:未捕獲的類型錯誤:無法讀取的未定義

以下哪個非混淆JS代碼匹配屬性「原型」(由TSC命令生成):

var __extends = this.__extends || function (d, b) { 
    function __() { this.constructor = d; } 
    __.prototype = b.prototype; 
    d.prototype = new __(); 
} 

此部分用於翻譯「擴展」Typescript關鍵字,而b的等效項未定義。

是否有人得到類似的錯誤或/並得到一個解決方案,能夠用一個Typescript編譯文件谷歌關閉混淆?

我嘗試使用uglifyjs命令並且輸出文件完美地工作,但我希望完全混淆(類,參數,變量,方法等)。此外,Google Closure提供的額外優化將受到歡迎。

謝謝你!

+0

Closure編譯器和UglifyJS都不混淆javascript。兩者都縮小了它,是的,這使得它更難閱讀 - 但它仍然是相同的腳本。如果你通過美化器運行輸出,你會得到原始的腳本 - 儘管它會被刪除註釋並具有不同的變量名稱。 – AHM

+2

@AHM這不是Closure編譯器的真實情況。這是一個真正的優化編譯器,它可以通過非平凡的方式更改代碼。在許多情況下,美化代碼不會給你任何接近原始腳本的東西。 –

+0

是的,但即使打開了高級優化,代碼也不會被混淆。任何熟悉JavaScript的人都能理解代碼的作用。如果目標是最小化和優化代碼Closure是一個好工具,但如果目標是混淆它,我認爲它不是很有用 – AHM

回答

0

好吧,我發現這個問題。

正如我剛纔所說,B是未定義:

var __extends = this.__extends || function (d, b) { 
    function __() { this.constructor = d; } 
    __.prototype = b.prototype; 
    d.prototype = new __(); 
} 

當打字稿「編譯」成JavaScript,如果你有一個命名空間的項目,但你寫在分隔的文件,與此相關的命名空間中的所有類,打字稿不要在最後生成的js文件如下:

var namespace; 
(function (namespace) { 

    var Class1 = (function (dependency) { 
     [...] 
     return Class1; 
    })(namespace.dependency); 

    namespace.Class1 = Class1; 
})(namespace || (namespace= {})); 

var namespace; 
(function (namespace) { 

    var Class2 = (function (dependency) { 
     [...] 
     return Class2; 
    })(namespace.dependency); 

    namespace.Class2 = Class2; 
})(namespace || (namespace= {})); 

var namespace; 
(function (namespace) { 

    var Main = (function (dependency) { 
     [...] 
     return Main; 
    })(namespace.Class2); 

    namespace.Main = Main; 
})(namespace || (namespace= {})); 

我不知道它是如何工作的,而是介於谷歌關閉編譯器移除了一些類即使有這個代碼沒有問題,JS可以處理它。所以一些依賴關係丟失了,而b是未定義的。

所以我發現如果你像下面這樣聲明你的命名空間,你將不會再遇到這個錯誤了(只要使用了「Main」類,閉包會保留所有的類在最終混淆的js文件中,或者你請在全局窗口對象中保留對您的命名空間的引用):

var namespace; 
(function (namespace) { 

    var Class1 = (function (dependency) { 
     [...] 
     return Class1; 
    })(namespace.dependency); 

    namespace.Class1= Class1; 

    var Class2 = (function (dependency) { 
     [...] 
     return Class2; 
    })(namespace.dependency); 

    namespace.Class2= Class2; 

    var Main = (function (dependency) { 
     [...] 
     return Main; 
    })(namespace.Class2); 

    namespace.Main = Main; 
})(namespace || (namespace= {})); 

我想我將在typescriptlang.org上打開一個問題。它正在優化生成的文件大小。

謝謝你的回答!

3

__extends的定義有一個問題,最有可能導致您看到的錯誤。

var __extends = this.__extends || function (d, b) { ... }; 

this.__extends參考意思是一樣的東西window.__extends,但是封閉,編譯器不知道(或曾經甚至試圖)認識到,在全球範圍內引用this實際上是在window對象。與--warning_level=VERBOSE的編譯器編譯會發出警告:

Dangerous use of the global this object at line 1 character 16 
var __extends = this.__extends || function (d, b) { 
       ^

此外,this.__extends是到外部/未定義屬性的引用和編譯器也警告有關上VERBOSE水平。

我修改和使用Closure-compiler Service UI註釋的定義編譯沒有警告:

// ==ClosureCompiler== 
// @compilation_level ADVANCED_OPTIMIZATIONS 
// @warning_level VERBOSE 
// @output_file_name default.js 
// @formatting pretty_print 
// ==/ClosureCompiler== 

var __extends = window['__extends'] || function (d, b) { 
    /** @constructor */ 
    function __() { this.constructor = d; } 
    __.prototype = b.prototype; 
    d.prototype = new __(); 
} 

/** 
* @constructor 
* @extends {String} 
*/ 
function foo2() {this.foo = 'bar'; } 
__extends(foo2, String); 

var bar2 = new foo2; 
alert(bar2.toLowerCase); 

A JSFiddle of the modified and compiled code

+0

還有一個問題,但這個答案有助於找到答案。謝謝! – NinjaFisherman