Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在缩小过程中排除调试JavaScript代码_Javascript_Compression_Minify_Google Closure Compiler - Fatal编程技术网

在缩小过程中排除调试JavaScript代码

在缩小过程中排除调试JavaScript代码,javascript,compression,minify,google-closure-compiler,Javascript,Compression,Minify,Google Closure Compiler,我正在研究缩小JavaScript代码的不同方法,包括常规、打包和解决方案。我真的很感兴趣的新,因为它看起来异常强大 我注意到它有一个功能,可以排除以三个分号开头的代码行。这便于排除调试代码。例如: ;;; console.log("Starting process"); 我花了一些时间清理我的代码库,并希望添加类似这样的提示,以便轻松排除调试代码。在准备过程中,我想弄清楚这是不是最好的解决方案,或者是否有其他技术 因为我还没有选择如何缩小,我想以一种与我最终使用的任何缩小器兼容的方式

我正在研究缩小JavaScript代码的不同方法,包括常规、打包和解决方案。我真的很感兴趣的新,因为它看起来异常强大

我注意到它有一个功能,可以排除以三个分号开头的代码行。这便于排除调试代码。例如:

;;;     console.log("Starting process");
我花了一些时间清理我的代码库,并希望添加类似这样的提示,以便轻松排除调试代码。在准备过程中,我想弄清楚这是不是最好的解决方案,或者是否有其他技术

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

  • 使用分号是一种标准技术,还是有其他方法

  • Packer是唯一提供此功能的解决方案吗

  • 其他解决方案是否也能适应这种工作方式,或者它们是否有其他方法来实现这一点

  • 我可能最终会开始使用闭包编译器。我现在该做些什么准备呢


  • 到目前为止,我还没有研究过缩小,但这种行为可以通过使用简单的正则表达式来实现:

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

    sed 's/;;;.*//g' < infile.js > outfile.js
    
    /** @define {boolean} */
    var DEBUG = true;
    
    sed的/*//g'outfile.js
    

    顺便说一句,如果您想知道压缩版本或缩小版本是否会“更好”,请阅读。

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

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

    // #ifdef debug
    var trace = debug.getTracer("easyXDM.Rpc");
    trace("constructor");
    // #endif
    
    在其中定义pragma,例如
    debug

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

    //此文件将不包含调试代码
    //此文件将
    
    以下是我在闭包编译器中使用的内容。首先,您需要定义如下调试变量:

    sed 's/;;;.*//g' < infile.js > outfile.js
    
    /** @define {boolean} */
    var DEBUG = true;
    
    它使用JS注释来进行闭包,您可以阅读

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

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

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

    如果在高级模式下使用闭包编译器,可以执行以下操作:

    if (DEBUG) console.log = function() {}
    
    console.log = console.debug = console.info = function(){};
    
    然后编译器将删除所有console.log调用。当然,您需要在命令行中定义变量
    DEBUG

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

    为什么不考虑Dojo工具包呢?它具有内置的基于注释的pragma,用于根据构建包含/排除代码段。另外,它在高级模式下与闭包编译器兼容(请参见下面的链接)

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

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

    这甚至适用于
    简单的优化
    ,而且不需要
    ——define=

    我使用了以下自制stuf:

    // Uncomment to enable debug messages
    // var debug = true;
    
    function ShowDebugMessage(message) {
        if (debug) {
            alert(message);
        }
    }
    

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

    ,即使这是一个老问题。我今天偶然发现了同样的问题,并发现它可以通过使用

    我跟着

    在将代码发送到客户机之前,我们在服务器上从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…等的所有调用。如果您正在使用,您可以使用drop_console参数删除console.*函数。

    在代码中登录到控制台的每个位置添加逻辑会增加调试和维护的难度

    如果您已经准备为生产代码添加一个构建步骤,那么您可以在顶部添加另一个文件,将
    控制台
    方法转换为
    noop

    比如:

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

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

    我使用@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");
    

    我在React应用程序中使用此选项:

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

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

    不要错过注释“/**@define{boolean}*/”,没有注释它就无法工作。这个答案应该在顶部。另一个好处是,在高级模式下,
    log
    函数将被剥离为死代码。这听起来非常有用。但是,在联机闭包编译器页面和本地测试它并没有效果。@hellectronic事实上它确实有效,您只需要将所有代码放入闭包中,否则编译器会认为它是全局变量,并且不会将其去掉。无论如何,这可能是最好的,这样您就不会全球化任何“use strict”语句。与使用传统的
    console.log()
    不同,这种方法的一大缺点是,当
    log=true
    时,dev tools中报告的
    log()
    的行号是定义此函数的位置,而不是调用它的位置。因此,所有消息都报告为在同一行上,而不是发生在何处。这是相当次优的,因为消息的行号通常是fo的关键