Feb26

Packing Prototype

In the last month or two we’ve had a number of tickets filed on the Rails Trac asking that Prototype adopt a more rigid syntax. Doing so would make it much easier to compress Prototype with tools like JSMin and Packer.

Opinions vary on this issue within the core team, but we all seem to agree that:

  1. We don’t want to distribute an official compressed version of Prototype.
  2. We don’t want to support a compressed version of Prototype. I’d rather eat glass than have to reconcile line numbers in a ticket someone filed against the compressed version.
  3. Some of the syntax requirements of compressors really harsh our mellow — for instance, Sam is not a fan of semicolons in one-line functions, whereas I really don’t want to wrap one-line if statements in braces. We don’t intentionally write malformed JavaScript, but as long as it can be parsed by a browser then it’s fine by us.
  4. Though there is a time and place for minification, we generally prefer other ways of reducing page weight: mod_gzip and proper caching, for instance.

Thus: any tickets created on this subject will be summarily closed.

But we’re not naive — we know people will compress Prototype whether we endorse it or not. Steve Kallestad distributes compressed versions of Prototype and Scriptaculous, managing to reduce Prototype’s file size from 64K to 25K. That’s compelling.

So if you want a compressed version of Prototype without having to put all those damned semicolons in by hand, use Dojo ShrinkSafe first. It uses Rhino, Mozilla’s JavaScript engine for Java, to parse and compress JavaScript safely, then outputs a strange-looking but syntax-abiding JavaScript file.

Here’s a quick workflow to compress whatever version of Prototype you please:

  1. Grab the most recent stable version of Prototype, the bleeding-edge version in source control, or whichever older version you prefer.
  2. ShrinkSafe it. You can do this on the Dojo website, from the command line, with a GUI version for OS X, or in TextMate with my JavaScript Tools Bundle. Some versions let you choose whether to strip newlines; for others you’ll have to do it manually.
  3. Run the resulting file through this online version of Packer. The JavaScript version on Dean Edwards’s site will not work — it chokes on a few properties that the PHP version does not. (Or you can experiment with some of the offline versions — .NET, PHP5, Perl — but I haven’t tested these myself.)
  4. Be safe: verify that your newly-compressed version of Prototype passes all unit tests. (No whining! If you’re old enough to compress then you’re old enough to run unit tests, son.)

Following these easily-automable steps allowed me to reduce version 1.5.0 of Prototype from 71K to 31K. So this is great news for all: those people who care so deeply about JS compression can integrate this into their build process, whereas those of us who contribute to Prototype can lazily and selfishly flout whatever syntax rules are not mandated by JavaScript interpreters.

Go nuts!

Comments

  1. Great Post Andrew.

    That should definitely go somewhere on the prototypejs.org website.

  2. Suppose you did add the semicolons and parentheses required by JSMin. How much smaller would the minimization be? I just think real numbers are more important then one’s “mellow”.

  3. @Henry: I gave real numbers, so I’m not sure what you’re asking about. How much smaller compared to what?

  4. I posted a 29KB version on TimTripcony.com that was created using the .NET version of Dean’s Packer. This compressed version also uses strict equality operators ( i.e. === instead of == where appropriate ), so various functions actually run faster, because temporary type coercion is avoided… strict adherence to spec isn’t just about appearance, after all.

  5. No whining! If you’re old enough to come up with something as kick-a## as prototype, you’re old enough to include semicolons and proper bracketing!

  6. @Marty: Touche. I’m just saying that what constitutes “proper” bracketing should be decided by a JavaScript interpreter, not a regex-based compression tool.

  7. Andrew I meant comparing how much smaller the minimized version would be if the semicolons were included and JSMin was used compare to shrinksafe minimized version where new lines are not stripped.

    JSMin is not regexp-based compression tool. It steps through the code one character at time. It is really a lexer that ignores unnecessary whitespace.

  8. @Henry: I don’t think the JSMin version would be any smaller. The only reason ShrinkSafe doesn’t strip newlines by default is to ensure line numbers match up in the compressed and non-compressed versions.

    Since in this example we’re packing even further, we can strip unnecessary newlines as well, thus going above and beyond what JSMin does.

    Back to the big picture, though: there is a limit to how much you can compress your code with a tool like JSMin or Packer. For a library like Prototype you won’t be able to get smaller than around 40% of the original size. Reducing Prototype’s size by 40K is worthwhile, but trying to squeeze out an extra few kilobytes on top of that isn’t. At that point you ought to gzip your files and/or get serious about ETags and If-Modified-Since.

  9. Why shrink safe first and then packer? Isn’t that minimizing twice?

    Also I think modgzip is for Apache 1.x. For Apache 2.x it is moddeflate.

  10. @Henry: Maybe I glossed over it in the post. The code ShrinkSafe generates abides by a strict syntax. It will automatically “fix” the things that compressors don’t like about Prototype’s syntax.

    So once you run Prototype through ShrinkSafe, you should be able to compress it with whatever else you choose. Packer can achieve much higher code compression than ShrinkSafe.

  11. Andrew. Thanks. I didn’t know that about shrinksafe

  12. Pingback Mar 3rd, 2007
    at 3:48 am

Painfully Obvious was built with WordPress, Prototype, Slicehost, and other accoutrements. Colophon →