简体   繁体   English

在缩小期间排除调试 JavaScript 代码

[英]Exclude debug JavaScript code during minification

I'm looking into different ways to minify my JavaScript code including the regular JSMin , Packer, and YUI solutions.我正在寻找不同的方法来缩小我的 JavaScript 代码,包括常规的JSMin 、Packer 和YUI解决方案。 I'm really interested in the new Google Closure Compiler , as it looks exceptionally powerful.我对新的Google Closure Compiler非常感兴趣,因为它看起来异常强大。

I noticed that Dean Edwards packer has a feature to exclude lines of code that start with three semicolons.我注意到Dean Edwards 打包程序具有排除以三个分号开头的代码行的功能。 This is handy to exclude debug code.这很方便排除调试代码。 For instance:例如:

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

I'm spending some time cleaning up my codebase and would like to add hints like this to easily exclude debug code.我正在花一些时间清理我的代码库,并想添加这样的提示以轻松排除调试代码。 In preparation for this, I'd like to figure out if this is the best solution, or if there are other techniques.在为此做准备时,我想弄清楚这是否是最好的解决方案,或者是否有其他技术。

Because I haven't chosen how to minify yet, I'd like to clean the code in a way that is compatible with whatever minifier I end up going with.因为我还没有选择如何缩小,所以我想以一种与我最终使用的任何缩小器兼容的方式来清理代码。 So my questions are these:所以我的问题是:

  1. Is using the semicolons a standard technique, or are there other ways to do it?使用分号是一种标准技术,还是有其他方法可以做到这一点?

  2. Is Packer the only solution that provides this feature? Packer 是唯一提供此功能的解决方案吗?

  3. Can the other solutions be adapted to work this way as well, or do they have alternative ways of accomplishing this?其他解决方案是否也可以适应这种方式,或者他们是否有其他方法来实现这一点?

  4. I will probably start using Closure Compiler eventually.我可能最终会开始使用 Closure Compiler。 Is there anything I should do now that would prepare for it?我现在应该做些什么来为它做准备吗?

here's the (ultimate) answer for closure compiler :这是闭包编译器的(最终)答案:

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

this will even work with SIMPLE_OPTIMIZATIONS and no --define= is necessary !这甚至可以与SIMPLE_OPTIMIZATIONS一起使用,并且不需要--define=

Here's what I use with Closure Compiler.这是我与 Closure Compiler 一起使用的内容。 First, you need to define a DEBUG variable like this:首先,您需要像这样定义一个 DEBUG 变量:

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

It's using the JS annotation for closure, which you can read about in the documentation .它使用 JS 注释进行闭包,您可以在文档中阅读。

Now, whenever you want some debug-only code, just wrap it in an if statement, like so:现在,只要您想要一些仅用于调试的代码,只需将其包装在 if 语句中,如下所示:

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

When compiling your code for release, add the following your compilation command: --define='DEBUG=false' -- any code within the debug statement will be completely left out of the compiled file.编译发布代码时,添加以下编译命令: --define='DEBUG=false' -- 调试语句中的任何代码都将完全排除在编译文件之外。

A good solution in this case might be js-build-tools which supports 'conditional compilation'.在这种情况下,一个好的解决方案可能是支持“条件编译”的js-build-tools

In short you can use comments such as简而言之,您可以使用诸如

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

where you define a pragma such as debug .在其中定义编译指示,例如debug

Then when building it (it has an ant-task)然后在构建它时(它有一个蚂蚁任务)

//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"/>

Adding logic to every place in your code where you are logging to the console makes it harder to debug and maintain.在代码中记录到控制台的每个位置添加逻辑会使调试和维护变得更加困难。

If you are already going to add a build step for your production code, you could always add another file at the top that turns your console methods into noop 's.如果您已经准备为您的生产代码添加构建步骤,您总是可以在顶部添加另一个文件,将您的console方法转换为noop的。

Something like:就像是:

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

Ideally, you'd just strip out any console methods, but if you are keeping them in anyway but not using them, this is probably the easiest to work with.理想情况下,您只需删除任何console方法,但如果您保留它们但不使用它们,这可能是最容易使用的。

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

If you use the Closure Compiler in Advanced mode, you can do something like:如果您在高级模式下使用 Closure Compiler,您可以执行以下操作:

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

Then the compiler will remove all your console.log calls.然后编译器将删除所有 console.log 调用。 Of course you need to --define the variable DEBUG in the command line.当然你需要在命令行中--define变量DEBUG

However, this is only for Advanced mode .但是,这仅适用于高级模式 If you are using Simple mode, you'll need to run a preprocessor on your source file.如果您使用的是简单模式,则需要在源文件上运行预处理器。

Why not consider the Dojo Toolkit?为什么不考虑 Dojo Toolkit? It has built-in comment-based pragma's to include/exclude sections of code based on a build.它具有内置的基于注释的编译指示,可以根据构建包含/排除代码部分。 Plus, it is compatible with the Closure Compiler in Advanced mode (see link below)!另外,它与高级模式下的闭包编译器兼容(见下面的链接)!

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

I use this in my React apps:我在我的 React 应用程序中使用它:

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

In other words, console.log will return nothing on prod enviroment.换句话说, console.log不会在 prod 环境中返回任何内容。

Even though its an old question.尽管这是一个老问题。 I stumbled upon the same issue today and found that it can be achieved using CompilerOptions .我今天偶然发现了同样的问题,发现可以使用CompilerOptions来实现。

I followed this thread .我跟着这个线程

We run the compiler, from Java, on our server before sending the code to the client.在将代码发送到客户端之前,我们在服务器上运行 Java 编译器。 This worked for us in Simple mode.这在简单模式下对我们有用。

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();
}

It will remove all the calls to logger.debug, logger.dev...etc.etc它将删除对 logger.debug、logger.dev...etc.etc 的所有调用

I am with @marcel-korpel.我和@marcel-korpel 在一起。 Isn't perfect but works.不完美但有效。 Replace the debug instructions before minification.在缩小之前替换调试指令。 The regular expression works in many places.正则表达式适用于许多地方。 Watch out unenclosed lines.注意未封闭的线路。

/console\.[^;]*/gm

Works on:适用于:

;;;     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;
}

Don't works:不工作:

console.log("instruction without semicolon")
console.log("semicolon in ; string");

I haven't looked into minification so far, but this behaviour could be accomplished using a simple regular expression:到目前为止,我还没有研究过缩小,但是这种行为可以使用一个简单的正则表达式来完成:

s/;;;.*//g

This replaces everything in a line after (and including) three semicolons with nothing, so it's discarded before minifying.这将替换(包括)三个分号之后(包括)一行中的所有内容,因此在缩小之前将其丢弃。 You can run sed (or a similar tool) before running your minification tool, like this:您可以在运行缩小工具之前运行sed (或类似工具),如下所示:

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

BTW, if you're wondering whether the packed version or the minified version will be 'better', read this comparison of JavaScript compression methods .顺便说一句,如果您想知道打包版本还是缩小版本会“更好”,请阅读JavaScript 压缩方法的比较

I was searching for a built-in option to do this.我正在寻找一个内置选项来执行此操作。 I have not found that yet, but my favorite answer also does not require any changes to existing source code.我还没有发现,但我最喜欢的答案也不需要对现有源代码进行任何更改。 Here's an example with basic usage .这是一个基本用法的例子。

Assume HTML file test.html with:假设 HTML 文件test.html包含:

<html>
        <script src="hallo.js"></script>
</html>

And hallo.js with:hallo.js

sayhi();
function sayhi()
{
        console.log("hallo, world!");
}

We'll use a separate file, say noconsole.js , having this from the linked answer:我们将使用一个单独的文件,比如noconsole.js ,它来自链接的答案:

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

Then we can compile it as follows, bearing in mind that order matters, noconsole.js must be placed first in the arguments:然后我们可以如下编译它,记住顺序很重要, noconsole.js必须放在参数的第一位:

google-closure-compiler --js noconsole.js hallo.js --js_output_file hallo.out.js

If you cat hallo.out.js you'd see:如果你cat hallo.out.js你会看到:

console.log=console.debug=console.info=function(){};sayhi();function sayhi(){console.log("hallo, world!")};

And if I test with mv hallo.out.js hallo.js and reload the page, I can see that the console is now empty.如果我用mv hallo.out.js hallo.js测试并重新加载页面,我可以看到控制台现在是空的。

Hope this clarifies it.希望这可以澄清它。 Note that I have not yet tested this in the ideal mode of compiling all the source code with ADVANCED optimizations, but I'd expect it to also work.请注意,我尚未在使用ADVANCED优化编译所有源代码的理想模式下对此进行测试,但我希望它也能工作。

I've used following self-made stuf:我用过以下自制的东西:

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

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

So when you've declared variable debug which is set to true - all ShowDebugMessage() calls would call alert() as well.因此,当您声明设置为true的变量debug时 - 所有ShowDebugMessage()调用也会调用alert() So just use it in a code and forget about in place conditions like ifdef or manual commenting of the debug output lines.因此,只需在代码中使用它,而无需考虑ifdef或调试输出行的手动注释等适当条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在编译/缩小过程中摆脱JavaScript中不必要的调试代码? - How to get rid of unnecessary debugging code in JavaScript during the compilation/minification process? JavaScript压缩和混淆代码中的数字已更改 - Javascript minification and obfuscation changed numbers in code 从webpack缩小中排除模块 - Exclude module from webpack minification 用Ant排除目录和js缩小 - Exclude directory and js minification with Ant 缩小:使用正则表达式从JavaScript代码中删除换行符 - Minification: Using regex to remove linebreaks from JavaScript code 缩小javascript生成错误的功能,是我的代码不好? - Minification of javascript generating incorrect functionality, is my code bad? 什么是JavaScript代码的例子,其语义会因缩小而改变? - What's an example of JavaScript code whose semantics would be changed by minification? JavaScript代码不会在代码运行时执行,但是当我调试它并在控制台中执行时,它可以工作 - JavaScript code is not executed during the runtime of the code, but when I debug it and execute in console, it works 如何从Rails 3应用程序中排除调试JavaScript? - How to exclude debug javascript from rails 3 application? 用分号插入Javascript缩小 - Javascript minification with semicolon insertion
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM