38
votes

I have a lot of time invested in jquery and a large application built with it. Recently I've been reviewing Google Closure Library, but at this time have found it to be not nearly as elegant as jquery. I believe it may have some potential and will look into it more, but for now I intend to continue using jQuery as my base framework.

However, I'm extremely impressed with Google Closure Compiler. I would love to start using it during the build process of my application. Unfortunately, it isn't exactly clear how easy it will be to use it for projects that do not follow the standard Google Closure standards.

Are there any best-practices or good resources on developing jquery-based projects and using the Google Closure Compiler? For instance:

  1. Does it make sense to compile jquery and jquery-ui with it, or should I continue pointing to these resources on the google CDN? I'm sure my jquery and jquery-ui will be smaller since I don't use all features of the libraries, but pointing to a CDN increases the the chances the file is already be in a visitor's cache.

  2. My application is split into many files, with a file per function. I'd like to combine them in a specific order and minify them into a file per section on my site. I'd like to automate this process.

  3. Currently my project has a java backend and is built with Maven. Does it make sense to add Google Closure Compiler to this build process?

Basically, I'm looking for any good resources that are specific to using Google Closure Compiler with jQuery.

8

8 Answers

10
votes

Google Closure Compiler is jQuery or any other library agnostic. It has two types of optimizations -

  • Simple
  • Advanced

I tried applying advanced optimizations, but it severely broke my application. If it does the same, you could either try to fix your application, or use simple optimization. There was a 32% drop in size with simple optimizations, and around 68% with advanced optimizations, but that didn't work out anyways.

Moving the JS concatenation in an automated fashion to your build process is definitely the way to go. See JavaScript dependency management.

jQuery is already heavily optimized for byte-size, so I doubt you will be able to squeeze enough juice by using Google Closure Compiler, but it's worth a try when combined with your project.

I see Google Closure Library in a favorable light, but haven't gotten to using it, as I'm heavily invested in MooTools at this point. Looking at it's API, it seems it has a rather broad coverage on what it has to offer besides just DOM manipulations, AJAX handling, event handling etc.

10
votes

$(elem)['width']() instead of $(elem).width()

This works with ADVANCED_OPTIMIZATIONS, so that the closure compiler doesn't refactor the jQuery methods.

9
votes

I believe as of 1.4.2 (maybe earlier), jQuery is minified using Google Closure Compiler by default. So it's probably best to continue referencing jQuery/jQuery UI via the google CDN. However, there are still benefits to integrating the Closure compiler into your build process to combine and minify your JS files. Namely, reduced JS requests per page load and smaller data transfered in hopes of improving your client side page load performance. These are some of the challenges we encountered while integrating Closure compiler into our build process:

  1. Constructing compilation command - We needed a means of invoking the compiler with all the necessary parameters in an automated manner during the build process. For us, this meant writing a console app to construct the command. If shell scripting is available in your environment, that could be an advantage.

  2. Managing Dependencies - The Closure compiler does have the capability to automatically sort the order of the combined JS such that dependencies are preserved. In order to leverage this feature, the JS files must be annotated with goog.provide\goog.require to tell the compiler what the dependencies are (--manage_closure_dependencies). The compiler will also exclude any JS that isn't required (i.e. is not referenced via a goog.require statement) from the combined JS. Here are a few things to watch out for:

    • If you want to include all of you JS files in the combined output, ensure that you include a "manifest" JS file in the compilation that only contains goog.require statements for each file to be included combined script (i.e. no goog.provide statements).
    • If you aren't using the Closure Library, ensure that you are compiling using SIMPLE_OPTIMIZATIONS or higher. Otherwise, the compiler will not remove the goog.provide/goog.require statements. Alternatively, you could also define your own goog.provide/goog.require JS functions to avoid errors.
    • Ensure there are no cyclical dependencies, or face the consequences.
  3. Compiling a debug version of the combined script - If needed, you can compile a debug version of the combined script using the --formatting PRETTY_PRINT flag. This will output the equivalent script formatted with whitespaces intact for development/debugging.

Although, the Closure compiler documentation can be sparse at times, it does have enough to get started for the most part and is continuously improving - so check regularly for updates, not just SO ;)

Hope this helps.

5
votes

jQuery is not compatible (yet) with the Closure Compiler in advanced mode. I agree it would be a very good thing to make it compatible, because its method-chaining syntax lends very readily to prototype virtualization for much improved execution speed.

In fact, among the popular JavaScript libraries (other than Closure Library, that is), only the Dojo Toolkit is compatible with Closure Advanced mode.

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

4
votes

Getting jQuery to work well with closure compiler/advanced has been difficult for me, but since you're dealing with multiple files I think it's important that you look into the modules option here:

Using the --module option in Closure Compiler to create multiple output files

I've been digging around for good documentation on the web, but there is VERY VERY little. By using a single jQuery extern, I was able to compile with advanced fine -- with multiple files, etc.

@echo off
java -jar bin\compiler.jar ^
    --compilation_level=ADVANCED_OPTIMIZATIONS ^
    --externs "externs\jquery-1.8.js" ^
    --language_in=ECMASCRIPT5_STRICT ^
    --warning_level=VERBOSE ^
    --module_output_path_prefix .\compiled\ ^
    ^
    --module_wrapper core:"(function(){%%s%%})();" ^
    --js ".\corelib.js" ^
    --module core:1 ^
    ^
    --module_wrapper somescript"(function(){%%s%%})();" ^
    --js ".\some_other_runtime_loaded_script" ^
    --module somescript:1:core ^
    ^
    --module_wrapper somescript1:"(function(){%%s%%})();" ^
    --js ".\some_other_runtime_loaded_script" ^
    --module somescript1:1:core

descriptions

--module_wrapper name:wrapper

This allows you to wrap your scripts in a closure -- since the compiler by default will remove them. If you're using "use strict" like I am, that's a no no.

--module name:#:dependency

name       Name of the script that will get written
#          number of scripts above that line to include into this script
dependency What script does this depend on?
1
votes

Tauren, you can test your code by using closure-compiler home. You can import your JQuery library or something else and try it. If possible, define your JavaScript code by using anonymous function which avoids naming conflict. Use namespaces by using Google library provide function. Another good resource which can help you is Google JavaScript Style Guide

-1
votes

You may use kjscompiler: https://github.com/knyga/kjscompiler and specify any libraries you like as external. They would not be minified. Really nice solution.