Countdown to Grails 2.0: Static resources |
Web applications typically rely heavily on what we call static resources, such as Javascript, CSS and image files. In a Grails application, they are put into a project's web-app directory and then referenced from the HTML. For example,
<link rel="stylesheet" href="${resource(dir: 'css', file: 'main.css')}" type="text/css">
will create a link to the file web-app/css/main.css. All very straightforward. You might even think that the current support is more than sufficient for anyone's needs. What else would you want to do?
That's a good point. The answer depends on the complexity of your application, but let's start with the example CSS link above. Why do we have to type out the <link rel="..." href=...>? Just by looking at the extension, we know that the resource is a CSS file. We also know that CSS files should be linked into an HTML page using the above element. So we're basically doing a lot of typing for something that Grails should be able to handle itself.
"OK," I hear you say, "but we could add a tag for CSS links." Indeed we could, and Grails 2 will include a <g:external/> tag that intelligently picks the appropriate link type for the resource. But now consider production: wouldn't it be a good idea to bundle CSS and Javascript files together? What about compressing them? (As an aside, Yahoo provides a tool called ySlow that will give you hints on just these kinds of optimisation). So how do we implement such optimisations? You could probably do it on an ad-hoc basis, but doing so limits your options because you can't define relationships between resources. What we really want is some way of declaring resources in a central place and indicating which ones should be processed and bundled together.
If I have yet to persuade you that there could be a better way to manage static resources, then think about Grails plugins. Many of these provide their own static resources. In fact, some plugins provide the same resources as each other. For example older versions of the YUI, Bubbling and Grails UI plugins all include the YUI libraries. Do we really need multiple copies of entire Javascript libraries? Of course not. Part of the problem can be solved with inter-plugin dependencies, but that doesn't work well on its own because there is no way for a plugin to say that some of its resources depend on specific resources in another plugin. In the end, it's up to the developer to make sure that all the appropriate resources (including transitive dependencies) are included in each page. That may involve some trial and error to make sure all requires resources are linked into the page and in the correct order.
Fortunately, we can do better. Enter the Resources plugin.
Declarative resources
By installing just this one plugin, you can start declaring your static resources (Javascript, CSS, etc.) in reusable modules. You can then define dependencies between modules so that Grails knows exactly which resources a module requires, including those specified in transitive dependencies. As an added benefit, modules ensure that resources are always declared in the correct order in a page and that there are no duplicates. In doing so, modules take much of the pain out of static resource management.
Declaring modules
You can declare resource modules in both applications and plugins. There are a couple of ways of doing this, but the most common approach is to add one or more dedicated artifacts to the project. For an application this might be grails-app/conf/ApplicationResources.groovy. As another example, the YUI plugin has grails-app/conf/YuiPluginResources.groovy. The basic structure of these files looks like this:
modules = {
core {
resource url: 'js/core.js', disposition: 'head'
resource url: 'js/ui.js'
resource url: 'css/main.css'
resource url: 'css/branding.css'
resource url: 'css/print.css', attrs: [media: 'print']
}
utils {
dependsOn 'jquery'
resource url: 'js/utils.js'
}
forms {
dependsOn 'core', 'utils'
resource url: 'css/forms.css'
resource url: 'js/forms.js'
}
}
"core", "utils" and "forms" are the names of our application modules, and as you can probably guess, the "forms" module depends on both "core" and "utils". You can also see that the "utils" module depends on "jquery", which is a module provided by the jQuery plugin. This structure is best seen in diagrammatic form:
If we look a bit deeper into the above module definitions, we can see that individual resources are declared within a module using "resource" plus a URL. This URL is the location of the resource relative to the web-app directory in your project. If you wish, you can also add extra attributes for fine-grained control of resources, in particular via the "disposition" setting.
There are two standard dispositions: "head", meaning that a resource goes inside the <head> element, and "defer", which typically means the end of the body (although you have control over the exact placement as you'll see shortly). By default, CSS files have a disposition of "head" while Javascript files use "defer", but these defaults can be overridden on a per-resource basis.
We now have the basis for defining simple or complex networks of resource modules, with those networks crossing application and plugin boundaries. Even better from a user's perspective, it's up to the plugins to make sure that their modules include the appropriate resources and dependencies.
So, Grails may now be aware of what static resources your application and its plugins provide, but it still doesn't know which pages require which resources. For that, you have to make some modifications to your GSPs.
Including resources in a page
As you know, you previously had to declare all your CSS and Javascript links explicitly in your layouts and views. So how does this change with the Resources plugin? Instead of putting in links to individual resources, you declare which modules your page requires, which makes for much conciser <head> blocks. In addition, you specify where in the page the resource links should go. Here's an example of a very simple layout using Resources:
<html>
<head>
...
<r:require modules="common, jquery"/>
<r:layoutResources/>
</head>
<body>
...
<r:layoutResources/>
</body>
</html>
As you can probably work out, the <r:require> tag tells Grails which static resources to include in the page while the <r:layoutResources> tags specify where the links should go. You should have two <r:layoutResources> tags: one in <head> and the other in <body>. Any resource with a disposition of "head" will go where the first one is, while those with a disposition of "defer" will be inserted at the second's location.
That really is it! Most of the work goes into ensuring that your module definitions are correct.
What I have covered so far works really well for CSS, Javascript and favicon files because the Resources plugin knows what links to generate for them and where to put those links. But what happens with inline images and scripts?
Ad-hoc resources
The Resources plugin calls inline images and scripts "ad-hoc resources". These typically aren't declared in modules and are simply processed as and when they are encountered in the page. A standard inline image link looks something like:
<img src="${resource(dir:'images',file:'grails_logo.png')}" ... />
So how do we make the Resources plugin aware of the image file? We don't! As of Grails 2.0, the <g:resource/> tag (used as a method above) automatically registers the resource with the plugin if it's installed. That means all the magic performed by mappers (which I'll talk about in a bit) will be applied to the given resource. And of course, <g:resource/> can be used for any type of resource, not just images.
Inline scripts are a little different because they aren't links to external files. Yet they can still benefit from the Resources plugin. By default all inline scripts declared with the <g:javascript/> tag will behave as they always have done. But if you replace <g:javascript/> with the <r:script/> tag, the inline script will be moved to the location of the second <r:layoutResources/> (their default disposition is "defer"). You can also declare an explicit disposition so that the script goes into <head>. Best of all, the inline scripts retain the order in which they are declared in the page.
There is one other source of ad-hoc resources to mention: CSS. Stylesheets are a common way of specifying background and other types of image, but CSS files aren't processed as GSP files. Is the Resources plugin aware of these links? Fortunately, yes. Even though the Resources plugin modifies the URL paths for all the resources it manages, that doesn't matter to you because the plugin also updates the links in the CSS files automatically. Everything will just work!
Magic mappers
On its own, the Resources plugin makes the management of static resources much simpler than before. But that's only part of the story. Since the plugin knows about all the resources and controls the link generation for them, it can perform extra processing to add interesting behaviour. This processing is done by an extensible pipeline of mappers:
Don't take this diagram as an absolute and correct reference: as a user, the exact pipeline and how it works doesn't really matter. The key is that you can if you want add your own mapper implementations or simply install a plugin that provides some mappers of its own. The result is some very powerful features for near zero effort.
For example, let's say you have the Resources plugin installed, some modules defined, and your GSP views and layouts set up to use the appropriate tags. Simply by installing the Cached Resources and Zipped Resources plugins, you will immediately start satisfying some of the ySlow recommendations, such as having a long-dated Expires header and gzip compression for all your static resources (although you can disable gzip compression for specific file types such as images, which tend to be compressed already). It shouldn't be this easy, right? But it is.
Conclusion
The Resources plugin has been around for a little while and is already used in a few production sites. It's even in use on the Grails website. And no wonder: it combines much improved management of static resources with a mapper pipeline that allows for easy-to-use but powerful features. Experienced web developers will notice the difference immediately, and you can expect more and more plugins to come with Resources support in the future. It even has its own user guide.
Because of the advantages the plugin brings, Grails 2 makes it a default plugin for new Grails projects and also integrates it into some of the core tags, such as <g:resource>. But even if you can't use Grails 2 yet, you can still make use of it with older versions of Grails and benefit from great resource management with little effort. One of it's key design principles is that it can be installed in any Grails application without breaking anything.
Whichever version of Grails you use, installing this plugin will improve your life as a web developer. That's not something to be sniffed at.
Similar Posts
- Grails 1.3 Released
- Managing plugins with Grails 1.3
- First Grails Release Under the SpringSource Banner
- Using Micro Cloud Foundry from Grails
- Grails 1.1.1 released with Google AppEngine support






Tomas says:
Added on June 30th, 2011 at 12:16 pmOOooooo very nice!! I want the production release right now!!
Дмитрий says:
Added on June 30th, 2011 at 12:46 pmI tried this out with 1.3.7, ran into an issue with reloading resources in development mode. Probably a bug in Grails itself rather than plugin, but still had to give it up. Hopefully not an issue in 2.0 Also, JS libraries that have dynamic loaders built in will first hit a 302 redirect before loading source from plugin.
Dmitry.
Дмитрий says:
Added on June 30th, 2011 at 12:54 pmOne other thing. There is a way to declare different modules for different environments just by wrapping the modules block in the environments block. I think that's supper useful when you have different builds of the JS libraries (i.e. ExtJS comes in minified, debug, debug with comments, etc) and of course you can turn off compressor for Debug builds.
Dmitry.
yawn says:
Added on June 30th, 2011 at 9:01 pmAnyone else tired of Grails, presumably in an effort to stay "edgy", forcing everyone to learn something new every few months?
Per says:
Added on July 1st, 2011 at 6:44 amNice and long awaited functionality. Good work.
One comment though. Although YSlow believes it is a good idea to defer loading af JavaScript (i.e. insert the SCRIPT tags just before the enclosing BODY tag), it really isn't. PageSpeed agrees with me, so I believe the default disposition for JavaScript resources should be HEAD.
sewa mobil says:
Added on July 2nd, 2011 at 5:57 amNice article, thanks for the information.
Peter Ledbrook (blog author) says:
Added on July 4th, 2011 at 8:28 am@Dimitry: did you raise an issue? I haven't come across that problem myself.
Elisten says:
Added on July 5th, 2011 at 4:30 pmIs same functionality planned for spring mvc in near future?
Gabriel says:
Added on July 6th, 2011 at 8:40 amGreat news!
Are you planning to support CDNs for static resources? Scripts like JQuery are usually retrieved from Google or MS's CDNs.
See http://code.google.com/apis/libraries/devguide.html
Peter Ledbrook (blog author) says:
Added on July 7th, 2011 at 8:32 am@Per: PageSpeed says it's non-optimal, but the optimal solution is fairly involved. I think deferred loading is beyond the scope of the plugin, but at least you do have the option of specifying whether JS is deferred or not. It's probably work raising a JIRA issue to make the default configurable (head or defer).
@Elisten Not that I'm aware of, but I'll see if I can find out.
@Gabriel Some users are looking into. You can specify the location of a particular resource using an absolute URL if you want, but I don't think you will get compression and caching via the plugin. Still, that may be all you need, in which case the plugin does support CDNs
Also, you can configure different modules depending on the environment, so CDN URLs may only be configured for production for example.
Sean @ CNA Training says:
Added on July 14th, 2011 at 2:13 amNice. Peter, what other core tags, besides g:resource, does the Grail 2 integrate into?
Peter Ledbrook (blog author) says:
Added on July 14th, 2011 at 3:26 am@Sean:, and . The latter two are new to Grails 2 and documented here:
http://grails.org/doc/1.4.0.M1/ref/Tags/img.html
http://grails.org/doc/1.4.0.M1/ref/Tags/external.html
giony says:
Added on July 26th, 2011 at 5:30 pmthat sounds….fantastic.
question is: when will grails 2.0 arrive? I have a small project that i would be willing to test grails 2.0 with. In production even
Peter Ledbrook (blog author) says:
Added on July 27th, 2011 at 3:05 am@giony: We're aiming for mid-September. First Grails 2.0 milestone hopefully out this week.
Robert says:
Added on September 20th, 2011 at 9:49 am"without breaking anything" ?? it broke all my links. I have custom mappings for urls that go something like context/really-cool-widget.html, where the "html" file is really a SEF url and not a file. the resource tag now wants to put in context/static/really-cool-widget.html, and I can't seem to config that static out.
If you set the grails.resources.uri.prefix= property to null, it still uses static. if you set it to a blank string you get a double slash, e.g. context//really-cool-widget.html.
my only workaround at the moment is to use the resource tag and set my context to root.
Peter Ledbrook (blog author) says:
Added on September 20th, 2011 at 10:07 am@Robert: you should be able to use the grails.resources.adhoc.patterns setting. For example,
grails.resources.adhoc.patterns = ["*.html"]
But perhaps the tag is the wrong one to use anyway, if it's not really a link to a real resource?
Robert says:
Added on September 20th, 2011 at 10:32 amit seemed to be the only tag available that created a full link.
I started down the path of changing all my code so it doesn't use that tag at all. I tried setting the grails.resources.processing.enabled = false in config and it still seems to intercept urls. I have links to images from css and they don't work now, same 'static' url issue. To take your suggestion one further I also tried:
grails.resources.adhoc.patterns = ["*.html","/images/*", "*.css"]
and going to context/images/bg-tile.png redirects me to context/static/images/bg-tile.png
is there some way to completely disable this?
Todd says:
Added on October 24th, 2011 at 3:00 pmHave an issue where my css resource keeps 404ing. I turned up the logging and found an entry that said:
getOrCreateAdHocResource for [myResource], latch is null
getOrCreateAdHocResource for [myResource], creating resource as not found
Javascript resources seemed to work fine.
Any Ideas?
Grails-1.3.7, JDK-1.5 (nothing i can do about that), resources-1.1.1
Peter Ledbrook (blog author) says:
Added on November 28th, 2011 at 9:26 am@Todd: that could be a bug. There are quite a few fixes going into 1.1.2. You could also try downgrading to 1.0.2 for the moment. Note that if those 404s happen immediately after changing a resource file (e.g. a CSS) then you may just have to wait a little while the resources are processed.
Robert: Sorry for the long delay. I'll get Marc to take a look at your use case, but note that the adhoc patterns you specified include everything under /images, hence why you get a redirect for your image. If you don't want images to be intercepted by Resources, keep "/images/*" out of the adhoc patterns list.
George says:
Added on January 4th, 2012 at 5:22 pmNice functionality.
I am wondering though, how can I have ajax-loade javascript evaluated.
i.e. if you have a template with html/javascpit and render it via ajax the javascpit in the will not be executed.
The only workaround I found is including a r:layoutResources if the current request is an ajax request like this.
Am I missing something?
Peter Ledbrook (blog author) says:
Added on January 5th, 2012 at 7:36 amAnother option is to use a plain <script> tag, which doesn't hook into Resources. Probably the safest option for embedded Javascript.
George says:
Added on January 5th, 2012 at 3:42 pmUsing a plain in templates won't render the javascript correctly in the initial page load because the required libraries are loaded at the end of the page (same for ).
I follow an other approach described in http://stackoverflow.com/questions/8736277/grails-resources-plugin-and-ajax-loaded-javascript, but I don't know if there is a better solution.
Peter Ledbrook (blog author) says:
Added on January 6th, 2012 at 6:11 amIf your embedded JavaScript requires libraries, those should be declared in disposition 'head' rather than 'defer'. However, I added an answer to the StackOverflow question that should help.
George says:
Added on January 6th, 2012 at 6:23 amI will lose one ySlow goal if I use 'head' disposition for js
Thanks for the answer Peter.
Wayne says:
Added on March 23rd, 2012 at 7:30 pmHow does one go about setting up SWF files as a module? I'm trying to package a JS lib which depends on SWF files, which should be static resources; I have them stored in /media/ … how do I get these served?
dStinger says:
Added on May 17th, 2012 at 10:35 amHas anyone had a problem with absolutely no CSS rendering in IE, Page just renders with multiple errors.
Developer Tools shows
But nothing under CSS
Any thoughts?
Peter Ledbrook (blog author) says:
Added on May 21st, 2012 at 8:11 am@Wayne r:resource will work with SWF files, or g:resource in Grails 2.0 (if you want automatic caching and zipping).
Because SWF are (almost?) always used inline, there is no reason to declare them in modules.
@dStinger I've never seen this problem. What do the Developer Tools show? I think some of your text has failed to appear, perhaps because you used markup in the comment.
24 day challenge says:
Added on December 6th, 2012 at 7:47 amUsing a plain in templates won't render the javascript correctly in the initial page load because the required libraries are loaded at the end of the page (same for ).