我使用Typescript命令(tsc)创建一个包含所有平台类的Javascript文件。
tsc "./Main.ts" -out "./script/myProject_debug.js" --declarations
然后,我想用Google Closure(compiler.jar)来混淆这个文件,如下所示:
java -jar ./compiler/compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js "./script/myProject_debug.js" > "./script/myProject.js".
但是当我执行生成的混淆/优化代码时,我得到以下错误:Uncaught TypeError:无法读取未定义的属性'prototype'
匹配以下非混淆的JS代码(由tsc命令生成):
var __extends = this.__extends || function (d, b) {
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
}
此部分用于翻译“extends”Typescript关键字,而b的等价物未定义。
是否有人遇到类似错误或/并获得解决方案,以便能够使用Typescript编译文件与Google Closure进行混淆?
我尝试使用uglifyjs命令并且输出文件完美地工作,但我想要完全混淆(类,参数,变量,方法等)。此外,欢迎Google Closure提供的额外优化。
谢谢!
答案 0 :(得分:3)
__extends
的定义存在一个很可能导致您看到错误的问题。
var __extends = this.__extends || function (d, b) { ... };
this.__extends
引用与window.__extends
的含义相同,但Closure编译器不知道(或甚至尝试)实现对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);
答案 1 :(得分:0)
好的,我发现了问题。
正如我先前所说,b未定义于:
var __extends = this.__extends || function (d, b) {
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
}
当typescript“编译”成javascript时,如果你按项目获得了一个命名空间,但是你在分离的文件中编写了与这个命名空间相关的所有类,那么Typescript会在最终生成的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= {}));
我不确切知道它是如何工作的,但某些地方google-closure-compiler删除了一些类,即使这个代码没有问题,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上打开一个问题。它顺便优化了生成的文件大小。
感谢您的回答!