Javascript makeclosure编译器带日志函数用法

Javascript makeclosure编译器带日志函数用法,javascript,google-closure-compiler,Javascript,Google Closure Compiler,我有一个日志API,我想向一些内部JS代码公开。我希望能够使用此API进行日志记录,但仅限于在进行调试构建时。现在,我让它部分工作。它只记录调试版本,但当有常规版本时,对该API的调用仍在代码中。当我使用goog.DEBUG=false编译时,我希望闭包编译器删除这个基本上死的代码 日志定义: goog.provide('com.foo.android.Log'); com.foo.Log.e = function(message){ goog.DEBUG && Andr



我有一个日志API,我想向一些内部JS代码公开。我希望能够使用此API进行日志记录,但仅限于在进行调试构建时。现在,我让它部分工作。它只记录调试版本,但当有常规版本时,对该API的调用仍在代码中。当我使用goog.DEBUG=false编译时,我希望闭包编译器删除这个基本上死的代码

日志定义:

goog.provide('com.foo.android.Log');
com.foo.Log.e = function(message){
    goog.DEBUG && AndroidLog.e(message);
}
goog.export(com.foo.Log, "e", com.foo.Log.e);
AndroidLog是一个提供给webview的Java对象,它将在其中运行,并正确地外部化,如下所示:

var AndroidLog = {};

/**
 * Log out to the error console
 * 
 * @param {string} message The message to log
 */
AndroidLog.e = function(message) {};
然后,在我的代码中,我可以使用:

com.foo.Log.e("Hello!"); // I want these stripped in production builds
我的问题是:我如何提供这个API,在我的代码中使用这个API,但是当不使用goog.DEBUG=true编译时,如何删除对这个API的任何调用?现在,我的代码库因为一堆从未调用过的日志API调用而变得臃肿。我要把它移走

谢谢!

我不想像jfriend00建议的那样运行自己的脚本,而是看看编译器的define api(goog.DEBUG也是从这里来的),默认情况下,您有DEBUG,但在那里您可以自己编译。

好的,如果我停止导出com.foo.Log()及其方法,这很容易做到。如果我真的想在某些特定情况下登录,但仍然在我的内部代码中删除日志调用,我可以为此声明两个类:

// This will get inlined and stripped, since its not exported.
goog.provide('com.foo.android.Log');
com.foo.Log.e = function(message){
    goog.DEBUG && AndroidLog.e(message);
}
// Don't export.


// This be available to use after closure compiler runs, since it's exported.
goog.provide('com.foo.android.production.Log');
goog.exportSymbol("ProductionLog", com.foo.android.production.Log);
com.foo.android.production.Log.log = function(message){
    goog.DEBUG && AndroidLog.e(message);
}
// Export.
goog.exportProperty(com.foo.android.production.Log, "log", com.foo.android.production.Log.log);

闭包编译器在剥离代码中提供了四个选项:1)
stripTypes
,2)
stripNameSuffix
,3)
stripNamePrefixes
和4)
stripTypePrefixes
。闭包构建工具plovr通过其JSON
名称后缀strip
类型前缀strip
公开
stripNamesuffix
stripTypePrefixes

关于这些选项如何在结尾处起作用,有一些很好的例子:第442至444页的权威指南。以下行作为常见用例提供:

options.stripTypePrefixes = ImmutableSet.of(“goog.debug”, “goog.asserts”);
options.stripNameSuffixes = ImmutableSet.of(“logger”, “logger_”); 

为了理解这些选项的细微差别并避免潜在的陷阱,我强烈建议阅读《收尾:最终指南》中的完整示例

我修改了一个编译器并将其打包为npm包

你可以在这里找到它:


它将在编译期间剥离所有日志消息

OK,在进一步挖掘之后,外部函数似乎没有内联。我仍然希望找到一种解决方法,而不是使用goog.DEBUG预先结束每个调用&我自己用Python编写了一个小脚本,将所有调试msg从源代码中剥离出来,作为构建过程的一部分。我需要的时候也能找到。这很奇怪,因为它应该是一种常见的需求。是的,它是第一个代码块中的最后一行。这可能就是让我陷入麻烦的原因吧?如果(!goog.DEBUG)AndroidLog.e=function(){}在代码的开头?请注意,如果导出
com.foo.Log.e
,编译器将不会删除它。这没有抓住要点。关键不在于仅仅关闭调试输出(这很简单)。关键是在部署之前删除所有调试代码,这样就不会占用额外的空间,不会执行,甚至不会向世界显示。lennel,谢谢你的建议。正如jfriend00所提到的,这将允许我传入数据。我已经在使用通过goog.DEBUG参数传入的数据,它完美地剥离了函数体。但是这个空白函数体永远不会内联到我的代码中,以删除函数用法。我认为这是因为CC不能假设外部函数在运行时不会被修改?对不起,我去度假了。如果您在编译时将define变量设置为false,编译器将在高级模式下忽略该代码。谢谢!我应该提到的是,我正在使用closureant任务,因此无法直接传递编译器选项。我正在考虑将ant任务子类化,以便传入我自己的编译器选项,但我想首先询问是否有一种方法可以做到这一点。我还要看一下plovr。@SkyKelsey:上面提到的用于剥离代码的编译器选项是闭包编译器Java源代码,即CompilerOptions.Java的内部选项。然而,plovr使使用StripNameSuffix和stripTypePrefixes变得很容易,而无需编写Java代码。我目前正在为所有的闭包工具编写一套Ant任务,它们将提供额外的灵活性。希望它们能在2012年4月底之前发布。