Andy Pemberton Rotating Header Image

Compress your JBoss Portal Theme with pack:tag

The goal of this article is to show you how to use pack:tag to optimize the performance of your JBoss Portal theme. I’ve used this approach on a production JBoss Portal 2.6 implementation and tested the approach out in version 2.7.

JBoss Portal has a feature-rich theme framework where CSS and javascript resources are included in the Portal; building a custom theme is easy. Pack:tag is an open source project that optimizes performance for java-based web apps; it provides a JSP tag library that automatically minifies, compresses, and combines CSS and javascript resources.

As more rich features and dynamic components reach your portal, larger AJAX frameworks and CSS libraries are required to support them. Large downloads will not only make your Portal load slower, but will also take longer to execute when using the Portal. Also, Portals are no longer accessed solely inside the firewall, many companies use them to power external facing sites - so few assumptions should be made about client bandwidth. Compressing your Portal theme with pack:tag will lead to faster downloads and page response time.

Building a custom Portal theme is covered in depth elsewhere, so we won’t get into that here. Instead, let’s look at the steps necessary to get your theme working with pack:tag:

Install pack:tag

  • Place the packtag-X.X.jar in the WEB-INF lib of your theme. To use pack:tag with one of the out of the box themes, place the packtag JAR at: [PS_HOME]/server/default/deploy/jboss-portal.sar/portal-core.war/WEB-INF/lib
  • You’ll also want to place the packtag.properties file in WEB-INF

Pack Your Theme

  • By default, you should have theme resources defined in a *-themes.xml file - because pack:tag uses a tag library, we have to move these resources from the XML file and put them into your layout JSP page.
  • Add the pack:tag tld reference to your layout JSP:
    
    <%@ taglib prefix="pack" uri="http://packtag.sf.net" %> 
    
  • Wrap the resource references in the pack:tag; for our custom theme this looks something like:
    
    <pack:style>
    	<src>/styles/extjs/css/ext-all.css</src>
    	<src>/styles/extjs/css/xtheme-gray.css</src>
    	<src>/styles/app.css</src>
    </pack:style>
    
    
    <pack:script>
    	<src>/scripts/jquery/jquery.js</src>
    	<src>/scripts/extjs/adapter/jquery/ext-jquery-adapter.js</src>
    	<src>/scripts/extjs/ext-all-debug.js</src>
    </pack:script>
    

Limitations and Gotchas

  • In JBoss Portal themes, layouts and themes are loosely coupled: layouts are used to generate markup, while themes include CSS and javascript references to style the layout. If you’ve written a JBoss Portal theme before, you’re probably thinking that we just tightly coupled the layout and theme.
  • Well, this is true - but, it turns out that the mechanism that provides the loose coupling has some problems out of the box. For one thing, Portal reorders your script and CSS references in the worst possible way (placing all the links after the scripts). This violates Yahoo’s best practices for website performance.
  • So, we can work around the tight coupling we’ve added by creating an additional JSP include file that will store the css/js references for your custom theme(s). You can then dynamically reference the active theme to load the appropriate theme files. The following snippet will do the trick for JBoss Portal 2.6.X:
    
    <jsp:include page="includes/theme-${requestScope['RENDERCONTEXT'].themeContext.theme.themeInfo.name}.jsp" />
    
  • Additionally, introducing pack:tag can also cause unexpected issues with your theme. Because pack:tag combines all your resource requests into a single request (see the first Yahoo performance rule), image references in CSS files can break. So if you get 404s on resource requests after enabling pack:tag, you’ll know what to debug.

Example

Check out the following Firebug screen shots depicting the actual file size savings in our custom theme:

Custom Theme CSS Before pack:tag

Custom Theme CSS Before pack:tag

Custom Theme CSS After pack:tag

Custom Theme CSS After pack:tag

Custom Theme JS Before pack:tag

Custom Theme JS Before pack:tag

Custom Theme JS After pack:tag

Custom Theme JS After pack:tag

Results

That’s right! Adding pack:tag resulted in:

  • Total CSS file size downloaded went from 141KB to 21KB - ~15% the original size
  • 6 HTTP requests for CSS reduced to 2
  • Total javascript file size downloaded went from 2MB to 188KB - ~10% the original size
  • 21 HTTP requests for javascript reduced to 1

References and Tools

5 Comments on “Compress your JBoss Portal Theme with pack:tag”

  1. #1 Chris
    on Dec 8th, 2008 at 5:41 pm

    Nice!

    A couple of things from my experience with pack:tag:

    The ability to switch out underlying compression implementations is cool!

    It has some advanced caching techniques built in out of the box. You get all of the cache-control/304-status/expires headers set for you and it’ll configure ETags on its managed resources for you, too. You’ll notice it manages holding onto a cache of the relevant compressed scripts and can tell when the managed resources’ timestamps change and recompress/update its cache and relevant client-caching headers/etags.

    This won’t apply to everybody, but one thing to watch out for is a few libraries that don’t get along with p:tag. The first problem is if your library wants to pump generated scripts out of its own servlets (and not pack:tag’s) like DWR. If pack:tag can’t serve the script itself, it isn’t going to help you. We’ve just let the DWR servlet do its thing here, though it probably wouldn’t be hard to modify DWR to delegate serving these through packtag. Another problem child is script.aculo.us, which is too smart for its own britches to play nice with pack:tag; you include a main script.aculo.us script and it will determine which dependent scripts you’re using and pull those down. Again, no way for pack:tag to insert itself into the process here.

  2. #2 Chris
    on Dec 8th, 2008 at 5:45 pm

    Also you can override packtag.properties with a packtag.user.properties on a per-environment basis. This is useful to cut minification off for development environments. We’ve dropped in “cache.type=disabled” to do this.

  3. #3 Andy
    on Dec 8th, 2008 at 5:48 pm

    @chris - yeah, pluggable compression algorithms is defintely the ‘killer feature’ for me. Once someone surpasses the YUI compressor’s algorithm efficiency, pack:tag will still have its place!

  4. #4 Brandon
    on Dec 11th, 2008 at 11:50 am

    Great post, Andy! Extremely useful.

  5. #5 Andy
    on Dec 11th, 2008 at 11:55 am

    @Brandon - thanks man; feel free to share with your Amentra cohorts.

Leave a Comment