Wednesday, July 23rd, 2008

Combining JavaScript and CSS for Performance

Category: Performance, Yahoo!

Tenni Theurer of Yahoo! has a new performance post, this time focused on serving files faster by combining them:

One performance technique without having to simplify the page design is to combine multiple scripts into a single script, and similarly combine multiple stylesheets into a single stylesheet.

Combining multiple files reduces the extra bytes from HTTP headers as well as potential transfer latency caused by TCP slow starts, packet losses, etc.

Tenni continues to discuss the issue and a solution that Yahoo! implemented, a simple app that combines the files on the fly:

Combo Handler provides a way to allow developers to maintain the logical organization of their code in separate files, while achieving the advantages of combining those into a single file as part of the final user experience. It alleviates the need for the time-consuming re-build and re-push processes. In addition, Combo Handler integrates seamlessly into a content delivery network, taking full advantage of the benefits of a CDN while reducing the drawbacks of dynamically combining separate files.

We’ve been using this service across many Yahoo! properties for some time now to help improve end users’ response times. Thanks to the YUI team, it is now available to all of you that are using the Yahoo!-hosted YUI JavaScript files. (Note: Combo-handling of CSS files is not supported at this time.) Head over to the YUI Configurator to generate combo-ready filepaths customized for your specific YUI implementation.

What about the numbers though. Well, this simple technique saved HotJobs 8% on their response time, and this was on a page that already had an A grade in YSlow, so was highly optimized.

Combining six JavaScript files into one single JavaScript file improved performance by almost 8% on average for Yahoo! HotJobs’ users on broadband bandwidth speeds and 5% for users on lan. No design or feature changes required!

Posted by Dion Almaer at 8:14 am

3.8 rating from 52 votes


Comments feed TrackBack URI does the same thing in PHP.

Comment by Joeri — July 23, 2008

My company actually went ahead and decided to start building similar a month ago because of the lack of solutions in this area.
Maybe we’ll be able to drop the project! :)

Comment by JeromeLapointe — July 23, 2008

*start building SOMETHING similar*

Comment by JeromeLapointe — July 23, 2008

Our CMS, Bugano, already does this out of the box. We merge all scripts a given page is supposed to have into a single file, which gets its own URL, and is given an appropriate cache header. If the user changes any of the included stylesheets/javascripts, the header is reset.

Now all we need is YUI on-server to minify all scripts. Or something.

Comment by PresenceLayer — July 23, 2008

I’m with Joeri – use Minify!!! Combining, caching, minifying, customizable…
I can’t count how many times I’ve said this… yet people keep reinventing the wheel.

Comment by doublerebel — July 23, 2008

GWT exceeds at doing this in ways unlike any other toolkit, effectively reducing the number of HTTP requests to load an application down to two, and making all of the application’s code and data effectively cached forever.

It uses a number of mechanisms to do this. It compiles all of the source code and resources at once, aggressively optimizing and obfuscating the Javascript in ways far more compact than JS minifiers/packers. It allows all images to be auto-sprited. It can take sprited images, CSS, locale data, even Flash SWF, and effectively inline them into the same file containing the JS (using data URLs). It includes a CSS optimizer as well, so prior to packing the CSS, it optimizes it.

The end result, is that you can, if you choose, reduce your entire app down to 2 HTTP requests, the second being in the cache 99% of the time, bringing the amortized number of requests to 1. And the data that is cached/loaded, is extremely optimized for size and speed.

The only “downside” for some, is having to use Java. :)

Comment by cromwellian — July 23, 2008

A ColdFusion equivalent

Comment by williamukoh — July 23, 2008

‘The only “downside” for some, is having to use Java.’
Too bad that’s a deal breaker.

Comment by eyelidlessness — July 23, 2008

Any solutions for

Comment by arphen — July 23, 2008

“Too bad that’s a deal breaker.”

Only for some, and only in the near term. In the long term, GWT is bound to be multilingual and include front end support for compiling JS2, and perhaps Scala. The benefits to endusers are undeniable, and there are enough polyglot programmers who aren’t vehemently anti-Java zealots, that it is still worth evangelizing. It’s sad, but alot of AJAX advocacy really centers around Javascript zealotry.

Comment by cromwellian — July 23, 2008

“reduce your entire app down to 2 HTTP requests”

I’m not quoting as an attack on cromwellian, but it is wise to remember that reducing HTTP requests is useful only so far as you reduce the overall traffic incurred to download a site. Moreover, perceived responsiveness is a different beast — witness the oft-discussed lazy loading techniques, which increase the HTTP requests (only calling what’s necessary when necessary) but decrease the perceived response times.

To optimize download, the combined size of the file should not be larger than the size of the required individual files plus the HTTP headers to retrieve them. This means that at some point you should package your combined scripts so that nothing (or few things) extra gets downloaded for a given page. Bundling everything into one file may increase the download and render time for many pages on your site.

Comment by quixote218 — July 23, 2008

GWT only packages that which is executed, it prunes everything else. See my Google I/O presentation here: where over 100K of source is packaged into <800 bytes of download. It does not simply package everything together without regard to whether it is needed.

GWT will also soon provide a mechanism for compilation-split lazy-loads, combining the best advantages of GWT’s heavy optimizations and packaging, with the ability to indicate which parts of overall program control flow are required for startup vs capable of being deferred.

Even without deferred loading, GWT typically boasts perceived startup times that are fast, one of the best examples being the Dojo and ExtJS Mail and Feed reader samples vs GWT equivalents. The GWT versions with essentially the same functionality startup anywhere from 2x to 5x faster.

I would also quibble about the combined size vs individual file size + headers comment. You don’t want to just optimize bandwidth consumption, but also latency. Each HTTP request adds latency, even those over a reused and pipelined HTTP connection. When I look at network latency in Safari or Firebug, even on pipelined individual requests, I still see 10-40ms latency from the addition roundtrips.

Comment by cromwellian — July 24, 2008

For java developers who are not using GWT but still would like to have their javascript (and CSS) files combined, there is a project called JAWR. It helps in getting much better grades with YSlow, not only by combining the files, since it also sets long term expires headers, it changes a portion of the URL when the resource changes, etc. It supports several minification tools (JSMin and the YUI compressor) and sports a customizable postprocessing chain that does thing such as rewriting CSS URLs so they are not broken by being combined into a bundle with a different path.
Jawr makes all combination ops at server startup so it has zero overhead to each request and uses gzip compression in a configurable way.

Comment by jordi — July 24, 2008

I use pack:tag for this and it works wonders, handles all the minification and caching too.

Comment by MattCoz — July 24, 2008

Its really a great article….. thanx

Comment by SEOexpert — July 24, 2008

for anyone developing with JSP…MattCoz beat me to it!

Comment by mattkime — July 29, 2008

faster is not always better

Comment by Tribulus — September 22, 2008

Leave a comment

You must be logged in to post a comment.