Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Monday, March 23, 2009

Combining JavaScript Libraries

I've been continuing to do work on speeding up Tapestry performance; I think part of the Tapestry message is not just how easy it is to get started, but how the framework grows with you as your application, and your user base, grows.

One aspect of performance is speeding up server side operations, and Tapestry 5.1 has gone a long way down that path. However, there's only so far that can take you, especially since the lion's share of server-side time is spent waiting for database queries.

Another approach is to minimize both the number of requests and the size of the replies. Tapestry 5.1 will GZIP compress replies for dynamic page content and static asset files. That reduces the size of each reply (when the client supports GZIP compression, which all modern browsers do).

What about reducing the number of requests? As with all web applications, the HTML for the page is just the start: there's also requests for images, stylesheets and JavaScript libraries. Tapestry is already good at giving these resources version-numbered URLs and far future expires headers, so that the client browser can cache them aggressively.

Tapestry 5.1 now adds a feature to combine JavaScript libraries. Whatever JavaScript libraries are requested by components when the page renders are combined into a virtual asset: a URL that represents the combination of the individual JavaScript libraries. This virtual asset has an odd URL (there's some Base64 encoded data as part of the file name), but it also has a far-future expires header and may be served to the client GZIP compressed.

This helps a lot with first-time access to an application; page rendering is interrupted only long enough to download a single JavaScript resource, rather than a series of requests for the individual files. Given that JavaScript must be loaded, parsed and executed serially ... and that rendering of the page is on hold until that occurs, combining JavaScript in this way is a pretty big win, especially given the amount of server-side and client-side caching involved.

The best part is, like many features in Tapestry, there's no configuration to worry about. It just works, it's free, there's no special scripts or tasks to run as part of your build. Better yet, it defaults to off for development mode and defaults on for production mode.

Next release, we may try to minimize the JavaScript as well as compress it; minimizing means stripping out comments and unnecessary whitespace and shortening variable and function names. Again, this would happen on-the-fly.


Alfonso said...

By far, this is the best java web-framework. Live Class Reloading.. when it will be possible to live-reload resources files? (i.e. i18n files, etc) and reload other java classes like services classes?
And redefining the url mapper?
Thanks!! Great work!! Keep working!!

cryptfiend said...
This comment has been removed by the author.
Martin said...

one thing, what if page 1 uses:
a.js 200k
b.js 100k
c.js 50k

and page 2 uses:
a.js 200k
b.js 100k
c.js 50k
d.js 10k
e.js 10k

combining these libraries to one would force the client to download a+b+c again when visiting page 2.

perhaps with a way to configure which resources to combine you could add the libraries/plugins that are common across all pages so that they're combined into one file and then the rest into another so that page 2 hass two script tags - src="a+b+c.js" and src="d+e.js"

martin said...

This is a great feature indeed !

I just wanted to warn you about something. About the "odd url to the virtual resource" : some reverse proxies may have trouble with "strange" urls.

We had the problem with one of our big client when we used a similar feature that is in .Net Framework. The script was not loaded at all.

So please do not make urls "too odd" :)

David Peterson said...

Nice one!

+1 for URL mapping support :-)

Sergey said...

Have you considered to support google hosted versions of Prototype and Scriptaculous? That can help too.

See Prototype hosted on Google's servers

Howard said...


Tapestry introduces minor patches into Scriptaculous, so using a hosted version would not work well, as we would lose that patch.