Combining Javascript and CSS content
At the Rich Web Experience conference this week, there were many talks about performance and tools like ySlow. Everybody acknowledges that downloading lots of javascript and css with multiple script or link tags is a key reason that Ajax sites are slow to start, due to the latency of multiple round trips over the network. Yet almost every example I saw at the show had multiple script tags and css links.
More over, none of the frameworks that I know provide mechanisms for easily switching from development mode (with individual scripts and links) to production mode with combined scripts that are stripped and compressed and it is an error prone process to edit markup in the transition from development to production.
So I have written ConcatServlet that allows multiple scripts tags like:
<script type="text/javascript" src="js/behaviour.js"></script>
<script type="text/javascript" src="js/ajax.js&/chat/chat.js"></script>
<script type="text/javascript" src="chat/chat.js"></script>
to be replaced with the single tag:
<script type="text/javascript"
src="concat?/js/behaviour.js&/js/ajax.js&/chat/chat.js">
</script>
The same servlet can also be used for css links.
The servlet uses RequestDispatcher.include, so it can be used with dynamic scripts, such as those generated for DWR. The down side of this approach is that it can't get the last modified dates of the individual resources, so the browser will not well cache the combination. So the servlet may be run in development mode, where the content is always combined and served, or in production mode where the start time of the servlet is used as the last modified time. This is production, the servlet needs to be restarted before any changed scripts will be served in response to If-Modified-Since requests.
If this style of script and link tag is well received, then in future, the servlet could be modified to do a better job with detecting modifications, caching combinations and perhaps stripping comments and whitespace. It would also be possible to cache combinations in direct buffers so they can be served efficiently by Jetty's NIO layer.
This servlet will be in the utilities jar of the 6.1.6 Jetty release.
Posted at 10:02PM Sep 09, 2007 by gregw in General | Comments[9]
Posted by Tuomas Kiviaho on September 10, 2007 at 04:30 AM EST #
This could be combined with build-time XSLT transforms on templates to embed the scripts or stylesheets directly into key page templates. For example, a weblog would be better off embedding its CSS into each entry's page instead of using a link, in order to survive slashdot/digg/reddit effects.
The servlet approach seems like it could easily suffer from DOS attacks. For example, an attacker could use it to repeatedly concat one large file (e.g. an image or movie) multiple times, causing out-of-memory conditions or even out-of-disk-space conditions.
(Your comment editor disables Firefox's spellchecker's ability to suggest corrections via the context menu. It also forces the text to be almost unreadably small on my small-screen, high-DPI laptop screen. Otherwise, it seems quite nice.)
Posted by Brian Smith on September 10, 2007 at 08:39 AM EST #
Not that I am trying to discount your idea, as it is framework agnostic.
Posted by Alexandre Rafalovitch on September 10, 2007 at 11:31 AM EST #
this is still a pain in development mode.
However, the main thing that I am advocating is script and link tags that list multiple content. For production, it may be best to turn off concatenation and only server pre-concatenated bundles that are named
with the ?foo.js&bar.js style.
The key thing is to have markup that will not need to be changed between development and testing.
Posted by Greg Wilkins on September 10, 2007 at 08:36 PM EST #
Posted by Panagiotis Astithas on September 10, 2007 at 11:25 PM EST #
JBoss Seam has had a similar way of including resources (component interfaces) for a while, see end of chapter 10.1 in http://docs.jboss.com/seam/1.1GA/reference/en/html/remoting.html
Posted by Mike Wilson on September 18, 2007 at 04:52 AM EST #
http://www.galan.de/projects/packtag
It might give you some cool ideas.
Regards,
Chris
Posted by Jelan on October 12, 2007 at 01:08 AM EST #
ConcatServlet behaves the same way as my code: including static js files works fine, including dwr js files does not. The problem does not seem to be another filter or servlet.
Posted by cbh on February 28, 2008 at 08:37 PM EST #
However, the includes should work and if they are failing then I would suspect a buglet with DWR. Worth raising on the DWR list, as I know Joe is also concerned with the number of loads required and is likely taking his own actions to improve the loading.
Posted by Greg Wilkins on March 03, 2008 at 04:38 PM EST #