A Grails UI Performance Plugin

I wrote up some notes in my previous post about some recent work I’ve done implementing the Yahoo Performance Team’s 14 rules for UI Performance. We’d talked at work about making it a plugin, but I wasn’t sure if it was sufficiently different from the excellent Jawr plugin to justify it. So I took a look and I think that my approach has some benefits that do justify a second plugin.


One significant feature that I’m providing is versioning and far-future Expires headers and caching for images in addition to JavaScript and CSS. Of course images aren’t very compressible, so gzipping them doesn’t make much sense, but the image payload of most sites is going to be a lot larger than that of the .js and .css files, so it makes sense to try to get clients to cache those also.

Another is a taglib that helps keep javascript at the end of the page. Sitemesh gets in the way here – there can be a lot of code in your layout GSPs after the layoutBody call, so DependantJavascriptTagLib allows you to define one or more hidden JavaScript declarations in your GSPs and render them all from the layout at the end of the body (Sitemesh has “content” tags that support this but there’s a bug where script tags lose their opening bracket so I’m using a technique borrowed from here).

Finally there’s simplicity – this was designed as a Grails plugin, so it has a more focused feature set and has fewer moving parts, preferring convention over configuration.

Having said that, there are advantages and disadvantages of both approaches:

Reasons to use Jawr versus using this plugin:

  • a lot more features, e.g. I18n, DWR, and JSF support, choice of minification approach, etc.
  • more configurable, e.g. exclusion lists – I gzip/minify/version everything
  • it’s not Grails-specific, so the time you spend learning its features will be useful when you want to use it in non-Grails apps

Reasons to use this plugin versus using Jawr:

  • the bulk of the work is done during the build, so no temp files, everything is in the war and problems are caught during the build instead of after deployment
  • it versions and sets Expire on images, and rewrites inner urls in css files to point to versioned images
  • supports Sprites via a taglib
  • helps move JavaScript to the end of the body via a taglib
  • doesn’t use a servlet – only a few taglibs and a Filter, letting the container continue to serve static resources
  • less processing at the server – it only needs to check if client supports gzip when rendering <javascript>, <css>, and <img> tags in GSPs
  • more Grails-friendly – in development mode it does nothing, and is only enabled in production mode, so there’s no need to check for modifications since Grails doesn’t support that in production mode

So as you’ll see from the code, there’s not much to it:

  • the plugin script wires up a simple Filter that adds caching headers in production mode
  • an Events.groovy script hooks into the war building process and gzips/versions/minifies static resources before the war file is packaged
  • and five taglibs handle the work of inserting the correct version and paths for resources, choosing to render the path to the gzipped files if the client supports it

Downloading:

You can download an early version of the plugin here, and a sample app demonstrating its use here. I’m waiting on some feedback before I put it up at plugins.grails.org since it’s still got some rough edges. Note that they’re configured as Eclipse projects but I’ve removed the Grails classpath jar entries and replaced them with a User Library called ‘grails’ to simplify the classpath. Either create a similar User Library (just include everything in GRAILS_HOME/dist and GRAILS_HOME/lib) or just re-add those jars explicitly like you’d have in a regular app.

Testing it out:

First run “grails run-app” from the performance-test project. It’s a basic app with one domain class, but the point is to show that in development mode it functions just like an app without the plugin – it serves the files from the file system unchanged and with no extra headers.

But if you run “grails war” and deploy the war in a servlet container (I’ve only tested Tomcat 6.0.16) then you should be able to view the source and see that the .js and .css files, plus all images have versions embedded in the urls and the .js and .css are gzipped and minified, and that the appropriate caching headers are set. The source files are unchanged – you still get to develop with readable files, but when deployed in prod mode, the app is a lot more efficient.

Note that there are very few image files since most are rendered using sprite1.gif via CSS. Also check out http://localhost:8080/performance-test/sprite/index (and views/sprite/index.gsp) for an example of an inline image from a sprite, plus an example of deferred JavaScript.

To install the plugin in one of your apps run

grails install-plugin http://burtbeckwith.com/blog/files/68/grails-ui-performance-0.1.zip

Let me know about issues you find or questions you have.

9 Responses to “A Grails UI Performance Plugin”

  1. Martin Kremers says:

    Hey! The performance plugin seems not to work well!

    Images aren’t shown, the CSS stylesheet isn’t loaded …

    After the elements was versionized, the names in the .gsp pages reffer to their old name! But in the .jar they got a new name with version!

  2. Burt says:

    You need to use the provided taglibs to generate the CSS, JS, and image urls. The taglibs are aware of the versions and whether the client supports gzip. Check out the sample app for examples.

  3. […] – bookmarked by 2 members originally found by Karina131313 on 2008-09-20 A Grails UI Performance Plugin http://burtbeckwith.com/blog/?p=68 – bookmarked by 5 members originally found by mvboronowski on […]

  4. Richard says:

    Hi,
    I installed the plugin but have a problem with the version in the file name. I am running the app in jetty and using svn. When i use the special tag to serve the js in the page’s head the version comes in as null. Any ideas what i might be doing wrong?

  5. Burt says:

    @Richard could you write up a bug in JIRA with some more details? http://jira.codehaus.org/browse/GRAILSPLUGINS under the Grails-UI-Performance component.

  6. guru says:

    Hi I am using this plugin in a jboss environement , and it seems to be not working is there any configuration change do i need to make in the server side

  7. Maricel says:

    Hi Burt,

    I recently started integrating the ui-performance plug in in our Grails app, everything seems to work great in all browsers except IE (go figure). In IE I get javascript errors on the gzip files, something like character not support and object expected, if I open the gzip files in the IE developers tool all I see is a weird character, like if IE doesn’t know how to process these files. Do I need to do any extra configuration so this works for IE? Or is there any way so I tell the plug in that if the browser is IE to not include the gzip files?

    Thanks for your help,

    Maricel.

  8. pierre says:

    Hi Burt, Thank you for the plugin.

    However in my HTML source, I have a tag like this :

    but the browser (firefox and chrome latest versions) cannot read this zipped file.

    Is the plugin work with Grails 2.0.1 and what should I do ?
    I configured my Tomcat like this :

    I added also text/css, but it doesn’t work.

    Many thanks 🙂

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.