2010-05-29 24 views
36

我正在研究不同的方法來縮小我的JavaScript代碼,包括常規的JSMin,Packer和YUI解決方案。我對新的Google Closure Compiler非常感興趣,因爲它看起來非常強大。在縮小過程中排除調試JavaScript代碼

我注意到Dean Edwards packer有一個功能,可以排除以三個分號開頭的代碼行。這很方便排除調試代碼。例如:

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

我花了一些時間清理我的代碼庫,並希望添加這樣的提示以輕鬆排除調試代碼。爲此,我想弄清楚這是最好的解決方案,還是有其他技術。

因爲我還沒有選擇如何縮小,所以我想以與最終結果一致的方式來兼容代碼。所以我的問題是這些:

  1. 是使用分號標準技術,還是有其他方法來做到這一點?

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

  3. 其他解決方案是否可以適應這種方式工作,或者他們是否有替代方法來完成這個?

  4. 我可能會最終開始使用Closure編譯器。現在有什麼我應該做的準備呢?

回答

0

我沒有看過成微小至今,但這種行爲可以用一個簡單的正則表達式來完成:

s/;;;.*//g 

這之後替換行的一切(包括)三個分號與什麼也沒有,所以它在放棄之前就被拋棄了。你可以運行你的微小的工具,這樣之前運行sed(或類似工具):BTW

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

,如果你想知道的包裝版本或縮小的版本是否會「更好」,讀this comparison of JavaScript compression methods

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

時那麼這裏就是我用封編譯器使用。首先,你需要像這樣定義一個變量DEBUG:

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

它使用JS標註爲關閉,你可以讀到in the documentation

現在,每當你想一些只調試代碼,只需將它包裝在一個if語句,就像這樣:

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

當編譯要發佈的代碼,添加以下你的編譯命令:--define='DEBUG=false' - 調試語句中的任何代碼將被完全排除在編譯的文件之外。

+0

不要錯過註釋 '/ ** @define {}布爾* /',它不會工作沒有這個。 – Palani 2011-10-31 19:00:24

2

如果您在高級模式下使用關閉編譯器,你可以這樣做:

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

那麼編譯器將刪除所有的console.log調用。當然,您需要在命令行中輸入--define變量DEBUG

但是,這僅適用於高級模式。如果您使用簡單模式,則需要在源文件上運行預處理器。

爲什麼不考慮Dojo Toolkit?它內置了基於註釋的編譯指示來包含/排除基於構建的代碼段。此外,它與高級模式下的Closure Compiler兼容(請參閱下面的鏈接)!

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

54

這裏是爲關閉編譯器(終極)答案:

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

這甚至SIMPLE_OPTIMIZATIONS工作,沒有--define=是必要的!

+3

這個答案應該在頂部。一個好處是,在高級模式下,'log'函數將被作爲死代碼去除。 – 2012-03-13 14:46:17

+0

這聽起來非常有用。但是在線封閉編譯器頁面和本地測試它並沒有效果。 – hellectronic 2012-08-21 14:41:33

+0

@hellectronic實際上,它確實有效,你只需要將所有的代碼放入一個閉包中,否則編譯器認爲它是一個全局變量,並且不會去除它。這可能是最好的,所以你不要全球化任何「嚴格使用」的聲明 – ansiart 2012-12-10 20:37:05

0

我用下面的自制塞入:

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

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

所以,當你聲明的變量debug被設置爲true - 所有ShowDebugMessage()電話會叫alert()爲好。因此,只需在代碼中使用它,並忘記了諸如ifdef之類的條件或手動評論調試輸出行。

2

即使它的一個老問題。今天我偶然發現了同樣的問題,發現它可以使用CompilerOptions來實現。

我跟着this thread

在將代碼發送到客戶端之前,我們在我們的服務器上從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

1

如果您使用UglifyJS2,您可以使用drop_console參數刪除控制檯。 * 功能。

2

將代碼添加到您的代碼中登錄到控制檯的每個地方會使調試和維護變得更加困難。

如果您已經打算爲您的產品代碼添加構建步驟,您可以隨時在頂部添加另一個文件,將console方法轉換爲noop的方法。

喜歡的東西:

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

理想情況下,你只是去掉任何console方法,但如果你讓他們在過,但不使用它們,這可能是最容易的工作。

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"); 
相關問題