45

我正在寻找不同的方法来缩小我的 JavaScript 代码,包括常规的JSMin、Packer 和YUI解决方案。我对新的Google Closure Compiler非常感兴趣,因为它看起来异常强大。

我注意到Dean Edwards 打包程序具有排除以三个分号开头的代码行的功能。这很方便排除调试代码。例如:

;;;     console.log("Starting process");

我正在花一些时间清理我的代码库,并想添加这样的提示以轻松排除调试代码。在为此做准备时,我想弄清楚这是否是最好的解决方案,或者是否有其他技术。

因为我还没有选择如何缩小,所以我想以一种与我最终使用的任何缩小器兼容的方式来清理代码。所以我的问题是:

  1. 使用分号是一种标准技术,还是有其他方法可以做到这一点?

  2. Packer 是唯一提供此功能的解决方案吗?

  3. 其他解决方案是否也可以适应这种方式,或者他们是否有其他方法来实现这一点?

  4. 我可能最终会开始使用 Closure Compiler。我现在应该做些什么来为它做准备吗?

4

11 回答 11

64

这是闭包编译器的(最终)答案:

/** @const */
var LOG = false;
...
LOG && log('hello world !'); // compiler will remove this line
...

这甚至可以使用SIMPLE_OPTIMIZATIONS,没有--define=必要!

于 2011-05-11T19:45:52.020 回答
25

这是我与 Closure Compiler 一起使用的内容。首先,您需要像这样定义一个 DEBUG 变量:

/** @define {boolean} */
var DEBUG = true;

它使用 JS 注释进行闭包,您可以在文档中阅读。

现在,只要您想要一些仅用于调试的代码,只需将其包装在 if 语句中,如下所示:

if (DEBUG) {
  console.log("Running in DEBUG mode");
}

编译发布代码时,添加以下编译命令:--define='DEBUG=false'-- 调试语句中的任何代码都将完全排除在编译文件之外。

于 2010-07-08T14:03:39.477 回答
6

在这种情况下,一个好的解决方案可能是支持“条件编译”的js-build-tools 。

简而言之,您可以使用诸如

// #ifdef debug
var trace = debug.getTracer("easyXDM.Rpc");
trace("constructor");
// #endif

您在其中定义编译指示,例如debug.

然后在构建它时(它有一个蚂蚁任务)

//this file will not have the debug code
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.js"/>
//this file will        
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.debug.js" defines="debug"/>
于 2010-05-29T13:06:59.410 回答
5

在代码中记录到控制台的每个位置添加逻辑会使调试和维护变得更加困难。

如果您已经准备为您的生产代码添加构建步骤,您总是可以在顶部添加另一个文件,将您的console方法转换为noop's.

就像是:

console.log = console.debug = console.info = function(){};

理想情况下,您只需去掉任何console方法,但如果您保留它们但不使用它们,这可能是最容易使用的。

于 2015-07-24T18:41:56.387 回答
2

如果你使用的是UglifyJS2,你可以使用drop_console参数来移除 console.* 函数。

于 2014-02-25T04:28:34.870 回答
2

如果您在高级模式下使用 Closure Compiler,您可以执行以下操作:

if (DEBUG) console.log = function() {}

然后编译器将删除所有 console.log 调用。当然你需要命令行中--define的变量DEBUG

但是,这仅适用于高级模式。如果您使用的是简单模式,则需要在源文件上运行预处理器。

为什么不考虑 Dojo Toolkit?它具有内置的基于注释的编译指示,可以根据构建包含/排除代码部分。另外,它与高级模式下的闭包编译器兼容(见下面的链接)!

http://dojo-toolkit.33424.n3.nabble.com/file/n2636749/Using_the_Dojo_Toolkit_with_the_Closure_Compiler.pdf?by-user=t

于 2011-03-10T12:39:35.330 回答
2

尽管这是一个老问题。我今天偶然发现了同样的问题,发现可以使用CompilerOptions来实现。

我跟着这个线程

在将代码发送到客户端之前,我们在服务器上运行 Java 编译器。这在简单模式下对我们有用。

private String compressWithClosureCompiler(final String code) {
    final Compiler compiler = new Compiler();
    final CompilerOptions options = new CompilerOptions();
    Logger.getLogger("com.google.javascript.jscomp").setLevel(Level.OFF);
    if (compressRemovesLogging) {
        options.stripNamePrefixes = ImmutableSet.of("logger");
        options.stripNameSuffixes = ImmutableSet.of("debug", "dev", "info", "error",
                "warn", "startClock", "stopClock", "dir");
    }
    CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);

    final JSSourceFile extern = JSSourceFile.fromCode("externs.js", "");
    final JSSourceFile input = JSSourceFile.fromCode("input.js", code);
    compiler.compile(extern, input, options);
    return compiler.toSource();
}

它将删除对 logger.debug、logger.dev...etc.etc 的所有调用

于 2012-03-01T17:01:21.653 回答
2

我在我的 React 应用程序中使用它:

if (process.env.REACT_APP_STAGE === 'PROD')
  console.log = function no_console() {};

换句话说,console.log不会在 prod 环境中返回任何内容。

于 2019-12-11T22:00:03.317 回答
1

我和@marcel-korpel 在一起。不完美但有效。在缩小之前替换调试指令。正则表达式适用于许多地方。注意未封闭的线路。

/console\.[^;]*/gm

适用于:

;;;     console.log("Starting process");
console.log("Starting process");
console.dir("Starting process");;;;;
console.log("Starting "+(1+2)+" processes"); iamok('good');
console.log('Message ' +
    'with new line'
);
console.group("a");
console.groupEnd();
swtich(input){
    case 1 : alert('ok'); break;
    default: console.warn("Fatal error"); break;
}

不工作:

console.log("instruction without semicolon")
console.log("semicolon in ; string");
于 2015-11-04T21:29:44.763 回答
0

我用过以下自制的东西:

// Uncomment to enable debug messages
// var debug = true;

function ShowDebugMessage(message) {
    if (debug) {
        alert(message);
    }
}

因此,当您声明debug设置为的变量时true- 所有ShowDebugMessage()调用也会调用alert()。因此,只需在代码中使用它,就可以忘记ifdef调试输出行的原地条件或手动注释。

于 2012-02-19T19:27:14.523 回答
0

到目前为止,我还没有研究过缩小,但是这种行为可以使用一个简单的正则表达式来完成:

s/;;;.*//g

这将替换(包括)三个分号之后(包括)一行中的所有内容,因此在缩小之前将其丢弃。您可以sed在运行缩小工具之前运行(或类似工具),如下所示:

sed 's/;;;.*//g' < infile.js > outfile.js

顺便说一句,如果您想知道打包版本还是缩小版本会“更好”,请阅读JavaScript 压缩方法的比较

于 2010-05-29T12:30:29.713 回答