0

I've followed the advice from this other SO thread to remove console.log() statements from my code.

Unfortunately, now Closure compiler is removing my entire code and not just the console.log() statements.

Might someone explain this? I'm at a loss...

JS file 1

(function(){
/** @const */
LOG = false;

function log() {
    return console.log.apply(console, arguments);
}

LOG && log('hello world !');

var foo='bar';
LOG && log("foo"+foo);
})();

JS file 2

(function(){
/** @const */
LOG = false;    

function test(){
    alert('testing...');
}

var baz='bazzy';
LOG && log("baz"+baz);


})();

Closure compiler step:

$ java -jar compiler-latest/compiler.jar --js j1.js j2.js --js_output_file compiled.js 

Result:

(function(){LOG=!1})();(function(){LOG=!1})();
Community
  • 1
  • 1
tim peterson
  • 23,653
  • 59
  • 177
  • 299

1 Answers1

2

Because the compiler determines that the rest of your code is unreachable.

Both files have a constant LOG set to false and you are not exporting anything (goog.export* or window['...'] = ...). The code which could get executed has a LOG && in front of it, which means it is not executed.

Therefor nothing can get executed, and thus the compiler removes it all.

Why is function test remoed: nobody calls it, simple as that. Call it in one of your files, and the compiler won't strip it away.


You can (should, actually) define LOG and log only in one file. For that to work, remove the anonymous function call around your code in every file. You can tell the compiler to add it back to the compiled code with the commandline option:

--output_wrapper=(function(){ %output% })();

So your two files should look like this:

JS file 1

/** @const */
var LOG = false;

function log() {
    return console.log.apply(console, arguments);
}

LOG && log('hello world !');

var foo='bar';
LOG && log("foo"+foo);

JS file 2

function test(){
    alert('testing...');
}

var baz='bazzy';
LOG && log("baz"+baz);

// call test, so it a) isnt stripped and b) well, executed :)
test();

Also, you might want to put your global vars and functions into a "namespace" to not pollute the global scope:

// create namespace (which is just a normal object)
var MyNamespace = {};

// create a namespaced function
MyNamespace.test = function() {
    alert('test');
}

// call it
MyNamespace.test();
hagbard
  • 695
  • 3
  • 13
  • so to keep `test()` I need to declare it as `window['test']`? Same for other global variables? – tim peterson Sep 17 '13 at 21:38
  • if you want to have that exported, meaning callable from other non compiled code, yes. But for that rather use goog.exportSymbol() (doesnt really matter, but makes the intent a bit clearer, if someone else reads the code). – hagbard Sep 17 '13 at 21:39
  • All my code will be compiled into one file and doesn't need to be callable by other non-compiled code. I assume defining `LOG` in each file is wrong too. Would you mind including your answer how these two simple JS files should be changed in light of this? – tim peterson Sep 17 '13 at 21:42
  • Btw if i change it to `window['test']=function(){...` then the console.log code below that no longer is removed. confusing. – tim peterson Sep 17 '13 at 21:49
  • `goog.exportSymbol` is the correct way to export ONLY if you are using other parts of Closure-library. `window['test'] = test` is correct when NOT using Closure-library. I believe since your `test` function causes global side effects, exporting it is blocking subsequent removal. Try making your exports the last statement in the function wrapper. – Chad Killingsworth Sep 18 '13 at 14:32
  • 1
    @timpeterson just edited my answer for having LOG only on one file – hagbard Sep 18 '13 at 17:21
  • @ChadKillingsworth the compiler never removes exported stuff, thats the idea behind exports: some other code might call it. – hagbard Sep 18 '13 at 17:23
  • @hagbard thanks for the update. Super helpful. The reason I don't call `test()` is because it reality it is a function that is only called `onclick`. What do with functions,variables that are only called into action at a later date? – tim peterson Sep 18 '13 at 18:40
  • What do you mean by later? Your code has to either do something or export something in order for the compiler to not strip everything - aka to have reachable code. So if the only thing you have there is an event handler, either bind it in the js you want to compile - that is do something - or export the handler so code from the outside can use it later. – hagbard Sep 18 '13 at 20:05
  • @hagbard Correct - that is the purpose of exports. However the method used to properly export a symbol depends on whether or not the project is utilizing Closure-library. Many people use the compiler on projects that do not use Closure-library so `goog.exportSymbol` is not an option for them. – Chad Killingsworth Sep 19 '13 at 21:40