Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to preserve global variables in javascript when using Closure compiler with advanced optimization?

I have my own Javascript library, which I want to minify by using Google closure compiler with Advanced optimization. By looking at the docs I see how to declare functions which are used outside of the library.

However I couldn't find a way how to preserve global variables declared in my library. Closure compiler just removes them, because it thinks they are never used. Anybody can help ?

Edit: example code:

var variable_1 = true;

This is defined globally right at the beginning of my library, but it's never used in the library itself. It is used outside the library when it is included in some page. But that Closure compiler doesn't know and thats the reason it removes these declarations.

like image 379
Frodik Avatar asked May 28 '11 12:05

Frodik


People also ask

Why should we avoid global variables in JavaScript?

Avoid global variables or minimize the usage of global variables in JavaScript. This is because global variables are easily overwritten by other scripts. Global Variables are not bad and not even a security concern, but it shouldn't overwrite values of another variable.

Is it bad to use global variables in JavaScript?

Avoid globals. Global variables and function names are an incredibly bad idea. The reason is that every JavaScript file included in the page runs in the same scope.


2 Answers

The closure compiler cannot remove global variables declared as window["variable_1"] = true

I recommend you write to window directly for global variables and I also recommend you use string literals for your variable names so that closure doesn't minify it.

like image 67
Raynos Avatar answered Sep 22 '22 18:09

Raynos


Although you can refer to a "true" global variable through replacing all usage of that global variable with window["varname"], it is usually not a good idea to "pollute" the global namespace. The Closure Compiler is designed to discourage you from doing this.

CAVEAT: window["varname"] and var varname are not the same, as "window" may not always be the global object in non-browser environments. As a matter of fact, the Closure Compiler assumes that the global object and "window" are different. For example, window["varname"] will compile to window.varname instead of var varname. They are NOT the same, although in a browser they work similarly.

It is best to make a global namespace object, then only export that one object. All your "global" variables should become properties under this global namespace variable. Benefits:

  1. All those global variables are renamed to shorter versions
  2. Inlining of constants can happen
  3. The Closure Compiler automatically "flattens" the namespace anyway, so your code won't be any slower
  4. Superior obfuscation
  5. Your code also works in non-browser environments. Remember, "window" may not always exists (e.g. in server-side code) and the "global object" may not always be "window"

If you have global variables that the user must read/set to use your library, it is also discouraged. It is better to expose an API on the global namespace object, then expose the public API's as usual through the window object: window["myLib"]["setConfig"] = myLib.setConfig.

In your case, if you have global variables used in other parts of your non-Closure-Compiled code, you have to consider:

  1. Is it better to put the declaration of those variables outside of the file being compiled by Closure
  2. Why are you not putting the declaration of those variables together with the code using them
  3. Should you actually be Closure-compiling all the code instead of only a portion (it is possible? Do you use another library?)
like image 33
Stephen Chung Avatar answered Sep 21 '22 18:09

Stephen Chung