closure compiler - keep unused functions and don't rename the undefined - javascript

So closure compiler is great but exporting functions and defining externs seems to be too much manual work. Is there a way to tell the compiler that it should not remove any functions and should not rename any undefined functions?
I have 2 major reasons behind this:
If a function or property is not defined in the scope of the javascript document, then it's probably defined in an external file. Therefore, I wouldn't like these to be renamed.
If the function is defined in a given scope but isn't being called within the same scope, then it's probably being called in some external code. Therefore, I would like to keep this function in the file without renaming it.
This way, we could simply compile javascript files without worrying about external libraries and exporting functions that are called from html pages.

It very much sounds like you should run the compiler with the optimization level of SIMPLE_OPTIMIZATIONS. Don't be fooled by the name, as it still fully compiles your code. The main difference is that SIMPLE_OPTIMIZATION will not rename or eliminate dead code in the global scope. This means the requirements of externs and exports are no longer present.

To avoid this, I run the closure compiler on a complete script that is the concatenation of all the scripts of my application. So this is a two-step process :
1 - concatenate all
2 - run the closure compiler
Additionally, you may want (as I often do, due to problems with jquery before v1.8) to run the compiler with compilationLevel="simple".
Concatenation is very important as in general the slowness isn't related to the total size but mainly to the number of requests.
EDIT : of course you have to automate all this. I can provide you an ant task definition if you use ant.

Related

Google Closure Compiler ADVANCED_OPTIMIZATIONS - Exclude All function names

I'm using Google's Closure Compiler to reduce the size of my Java Script code. Unfortunately the Closure Compiler does also change ALL function names in the Advanced mode without an easy option to change that.
I do need to exclude functions that are defined as properties (e.g. car.bla = function() ) completely. This includes the ones that I use and that are not defined at all in the local code, and the ones that I define myself.
I know that there is externs and exports (although I don't fully understand them) but I do not want to have to keep maintaining any extra files beside my code.
I would also be find to exclude any functions (also non-property functions).
After googling for a few hours I've still not found an options for that.
There are a few answers here;
Use #export to label a property as "used by external sources", such as an Angular binding.
Create an externs. These are used when you have code that is compiled separately from your code, but they need to interact. Have a look at how simple Angular's externs are.
Reduce your compilation level to WHITESPACE_ONLY
Depending on your setup, you may be able to pass --property_renaming=ALL_UNQUOTED and use foo['bar'] to access foo.bar
Depending on your setup, you may be able to Pass --property_renaming=OFF

Can/will AMD modules load in-between in-line script tags?

For reasons that aren't relevant to the question, my coworker needs to load a script that uses the Universal Module Definition pattern. Our environment usually has an AMD tool loaded, but for more irrelevant reasons, my coworker needs the script to define a global rather than registering a module through AMD. The approach that is currently checked in on their branch is something along the lines of this:
<script>
var backupDefine = define;
define = null;
</script>
<script src="../path/to/some/script/using/UMD.js"></script>
<script>
define = backupDefine;
backupDefine = null;
</script>
My question is: Is this a horrible idea? Is there a guarantee in the way browsers load scripts from script tags that will ensure nothing other than loading the UMD-based script will happen between undefining define and restoring define? We have a very large, very heavily async asset load primarily based around AMD modules, so what I am concerned with is an AMD module attempting to define itself in that intermittent state where define is currently not defined.
So long as UMD.js in no way modifies the scripts in the DOM, those scripts are guaranteed to execute in the order that they're authored in before any asynchronous callbacks that may have been queued before the first script executes.
I see this as a bad idea and spec breaking even if the case where define is always necessary is rare or even non-existent due to <script> load order considering your case. In an AMD environment, define, require and the like should basically be treated as first class keywords since their goal is to help you to remove globals.
Realistically, you're treading into undefined behavior as far as I can tell and writing code that is hard to maintain. You're relying on a tricky case with a spec where you have to undefine something and them immediately redefine it hoping that nothing tried to use it in the mean time. I'd say that that's "unsafe".
If you really need this to happen, I'd comment and document it heavily to make sure a future developer doesn't misunderstand what you're doing. However, I would say the better course of action is to rewrite the UMD.js file so that you export your global your own way. Rhetorically, why are you trying to use UMD if you don't want it to UMD things?
You're writing this module to support AMD through UMD but then you say that you don't want it to be used by AMD. Rewrite the file to just export to the global and avoid messing with define before you accidentally conflict with an additional library that does something tricky with define.

Is it possible to load requirejs under a different name

I know that for design reasons requirejs doesn't offer a way to load itself in noContext mode, bound to a different variable. Is it possible to do this manually somehow, or does require utilize the specific word "require" to execute its code? I know that it needs to the "require" and "requirejs" global variables to work - is it possible to change these names?
A little context: I am building Chrome extension which needs to load requireJS on a page to load a decent number of modules. However, some pages (upworthy.com and slate.com being 2 prominent examples) have critical functionality already bound to the name "require" (in the case of upworthy, they use requirebin or browserify). So I want to load requireJS without interfering with whatever native functionality is already assigned to require.
The JavaScript execution environment of content scripts are separated from the page, so you should not have any namespace collisions.
If you really need to inject the script in the page, then I strongly recommend to use r.js to generate one single JavaScript file, wrapped in an anonymous self-invoking function. Then, the require variable of your script will not conflict with the one in the page.

Minimize and protect function names inside objects or in the global scope

I have tried to minimize my javascript files using YUI compressor, but to no end, I cannot get the names of functions inside objects to minimize. I have tried to minimize function names in the global scope, but have come to understand this is not possible. Is there any way to minimize javascript code in a way that renames the function names also? Perhaps by encapsulating them in an object somehow? Other than obfuscating, which I have read has quality implications, I cannot think of any other way to protect client side code. Thank You.
Closure-compiler does this when you use ADVANCED_OPTIMIZATIONS. Be warned however, that it does it to everything unless you take specific steps to prevent this. Converting a large code base to be compatible with ADVANCED_OPTIMIZATIONS can be daunting.
See Which Compilation Level is Right for Me?
If you are writing a library that others will consume, there are even more considerations.

requireJS : How to structure Javascript for an entire site?

I have 3000+ lines of javascript that I need to get into a sensible/maintainable structure. I have chosen to use requireJS as it has been recommend to me by a few people. I have a bunch of variables that are used throughout the application and need to be available everywhere. I also have a bunch of functions that need to be available everywhere. Apart from these two dependencies most of the code can be divided off into their own modules.
I am having trouble understanding how to manage my main variables so that if one module of code makes changes to the variables the rest of the JS modules will see that change. I think I need to see a few examples that demonstrate how requireJS is intended to work on a larger scale that the examples in the documentation.
If anyone is an experienced requireJS user I would love the hear your tips!
The whole point of RequireJS is to avoid the need for these global variables and global functions.
Can't you wrap those globals into a module, then depend on it in your other modules?
For example, a RequireJS modularized Dojo may be something like:
dojo/cache module
dojo/string module (requires dojo/cache)
dojo/date module (requires dojo/string)
dojo/cookie module (requires dojo/string)
:
:
dojo module (requires everything above, make them all into sub-objects, say, e.g. dojo.cache, dojo.string, dojo.date etc.)
user module #1 (requires dojo)
user module #2 (maybe only requiring dojo/string)
RequireJS gives you better options for encapsulating modules, but it doesn't change Javascript itself at all. As a transition strategy, you can still define your globals inside the function block. Depending on the module that contains these definitions will ensure that it has run before the dependent modules.
Next step would be to assign those methods to an object other than window, and then use that object through the variable received from RequireJS module dependency.
Hopefully by the time you've done this, you might have some insight into a cleaner solution. I refactored (and still am) a single-file project into several files, including optional plug-ins, although I did most of it before adding RequireJS to the mix.
See the RequireJS documentation:
Defining a module
Definition Functions with Dependencies
If the module has dependencies, the first argument should be an array of dependency names, and the second argument should be a definition function. ... The dependencies will be passed to the definition function as function arguments
define(["./cart", "./inventory"], function(cart, inventory) {
// ...
return { ... };
}
);
So I think you can define() your main module like all other modules and make the submodules depend on that main module. Then the module object is passed as an argument to the definition function of a submodule. You don't have to use global variables.
If you want to share information between modules, attach the information to the module object, and have the other modules rely on that module, and check its property.
If you have existing code, you can assign to window.x to provide a global x while you are cleaning it up.

Categories

Resources