Improve Grails Performance With Static Resources

Print This Post Print This Post

A simple concept: offloading static resources (images, javascript, css, etc) to a separate web server than your Grails application. The idea is that these resources don’t change (often) and tend to make up for a significant percentage of the actual browser requests. Sooo… why bother Tomcat (or whatever your favorite web container is) with serving things that Apache HTTPD can handle quite efficiently.

Apache

The basic Apache setup part is quite straight forward and out of scope here so I’ll leave that to the official documentation. I will, however, recommend the addition of a couple of modules: mod_headers and mod_expires. These two modules will allow you to control the caching of these resources in people’s browsers, further reducing the overall traffic to your site. Adapt the following to your configuration file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<Directory "/path/to/your/static/resources">
    ExpiresActive On
 
    # Default expire to a month after the modification date
    ExpiresDefault M2592000
 
    # Expire PNG images a month after they were accessed
    ExpiresByType image/png A2592000
 
    # Expire text to a week after they were accessed
    ExpiresByType text/plain A604800
 
    # Add cache-control header to the http response.
    Header Set Cache-Control "public"
</Directory>

Your Grails Application

The first step here would to be to add a setting in your Config.groovy that tells the application where the static resources are hosted from. An example would be:

1
myapp.staticresources.url = "http://www.mysite.com/static"

The actual implementation is a simple taglib with a tag that follows the existing g.resource closely. Create a taglib class called StaticResourcesTagLib (or whatever you’d like, really) and shape it like the following example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class StaticResourcesTagLib {
 
    // Change this to match your application
    static namespace = "wthr"
 
    def grailsApplication
 
    def staticResource = { attrs, body ->
        def dir = (attrs.dir) ? attrs.dir : ""
        def file = (attrs.file) ? attrs.file : ""
 
        def url = "${grailsApplication.config.myapp.staticresources.url}/${dir}/${file}"
        out << body() << url
    }
 
}

Using it in your GSP pages would look similar to this example:

1
<img src="${wthr.staticResource(dir:'/images',file:'someimage.png')}" />

While would result in a url of http://www.mysite.com/static/images/someimage.png for this image, which in turn gets cached in the browser for a month.

Testing

Adding this functionality to your application should not be done blindly. Very effective tools for testing the performance benefits would be Firebug for Firefox, and (my personal favorite) the new Speed Tracer extension for Google Chrome (see links below). Use these to verify that the caching and expire rules are getting set correctly and, in the case of Speed Tracer, make the suggested performance tweaks.

Alternate Method With mod_rewrite

In the case of a web application that you may not have the ability to modify (this applies to any Java framework, not just Grails), a good trick is to handle all requests through Apache (connected to Tomcat via mod_proxy_ajp) and use mod_rewrite to intercept requests for resources and serve them directly (without wasting Tomcat’s time). I was able to successfully use this for a web application that used the Seam framework on JBoss which had some annoying performance issues.
In the easiest scenario all the images or javascript, etc, would be stored in predetermined locations in the application (as opposed to oddly named jar files or scattered). Put the static resources on Apache in much the same layout as the application and add an adaptation of the following configuration directives:

1
2
3
4
5
RewriteEngine on
RewriteRule ^/myapp/images/(.*)    /myapp-static/images/$1
RewriteRule ^/myapp/css/(.*)    /myapp-static/css/$1
RewriteRule ^/myapp/js/(.*)    /myapp-static/js/$1
RewriteRule ^/myapp/swf/(.*)    /myapp-static/swf/$1

Links

Google Speed Tracer: http://code.google.com/webtoolkit/speedtracer/

Firebug: http://getfirebug.com/

RKYKB8TJ7MRK

2 thoughts on “Improve Grails Performance With Static Resources

  1. Pingback: Tweets that mention Improve Grails Performance With Static Resources ยป WTHR.US -- Topsy.com

  2. Pingback: Preprocessing CSS in Grails » WTHR.US