Wednesday, November 11, 2009

Closure and webOS

So I have spent the last few days messing around with Closure, Google's new javascript library, compiler, and templating.

First, the why
The Closure compiler from Google promises to do code optimization, inlining, and trimming all in one. So theoretically it would make the javascript faster and smaller which is a good thing especially when working on a mobile platform.

My first goal was to get gDial Pro to compile using the Closure compiler and its standard optimization level. This can be simple, just compiling each js file individually, which doesn't really give too much gain since a lot of the optimizations need to see all of the js code in one file in order to really do its magic.

So it should have been simple right, just pass in each js file on one line to the Closure compiler and let it work its magic which it did. The resulting code would not run though as it simply concatenates all the files together in the order passed in and compiles. In the gDial Code there are some js files that need to load in specific order after other files. So when they concatenate willy nilly, you get broken code as some objects/functions were not defined before where they were being used.

So to make it work, I needed to concatenate all of the javascript files in the order that they need to load and then run the compiler. This was easier said than done as I wanted a generic solution that didn't require me to hand edit the build file every time I added in a new javascript file or changed the load order. The solution is that the sources.json file already has my code listed in the order it needs to load. So, I created a sed command to parse that file for the filenames since they are already in order and concatenate them together, then run the Closure compiler.

Also, after this happens, all of the code for the app is now in a single output file and so that same sources.json file need replaced with a file referencing the single .js file that we have output from the Closure compiler.

And then it works!!!!

Gotchas
You can't use the object oriented inheritance from the Prototype library. (i.e. Class.create). The reason is due to the way that you make calls to super class functions in their system. They require that the function receive a special parameter named '$super'. Closure changes the name of all parameters to short 1 letter names for space reasons and so this '$super' variable will have its name changed which breaks the inheritance.

You can get around this by using the excellent Dojo Library and its class inheritance system which doesn't require the use of special variable names and works fine with the Closure compiler.

Also, I only apply the Closure compilation when building my production releases of the software as the name/file mangling would be a nightmare for use in debugging. So I debug my code and then I have a build script which runs the compiler on the code and builds my packages for distribution.

Forget about trying to run the compiler in advanced optimizations mode. Won't work as it really needs to be run on a single file with ALL of the javascript code and the Mojo Framework js code as well as their version of prototype get included into the app separately. I am sure someone will come up with a solution to this in the future, but for now I wouldn't recommend even trying it for the average app developer.

Also, for the same reasons, using the Closure Library is a no go as well. It has a package system that dynamically loads the js files it needs, but due to the way the webOS apps are loaded, the package system doesn't seem to work.

Worth it?
Tough question. Now that I am done with implementing it, the hard work is done and I will likely continue to use it as I plan to migrate to the Closure Library and Advanced Optimizations as techniques are discovered to make them work with webOS.

As to whether there is any performance increase in the resulting code, I am not sure as I just put it out there to the Homebrew community and I am awaiting feedback from all of the users on their experiences with the app. It was pretty optimized before and I was already minifying code with the YUI Compressor.

Only time will tell whether it was worthwhile.

5 comments:

  1. Under Gotchas
    "You can's use..."
    prolly should be
    "You can't use..."

    ReplyDelete
  2. Thanks Tom. Sometimes I rely too much on grammar and spell checking :)

    ReplyDelete
  3. Would you mind posting an example of your sed command?

    ReplyDelete
  4. Ken,

    If you promise not to laugh at my ridiculously bad sed skills, here it is:

    for file in $(sed -n -e 's/^.*\"source\": \"\(.*\)\".*/\1/gp' sources.json| sed -e 's:\\\/:/:g' )

    As soon as some sed expert comes by I would bet they come up with a much more elegant way to loop through the files in the sources.json.

    ReplyDelete
  5. HA HA HA. Ha, ha ha... Sorry, it was something you sed. :)


    Much better than my non-existant sed skills.

    ReplyDelete