Optimising your Application with Grails Resources Plugin

Posted by: on Sep 12, 2011 | 31 Comments

It’s been nearly a year since we first announced the Resources framework for Grails. It’s about time we looked at some of the more advanced features that it provides so that you can make the most of this very powerful plugin.

The start of this article will go over some of the basics again, as they are a prerequisite for understanding the more advance topics covered later in the piece.

UPDATE: I am considering writing a small e-book giving more detail and depth on this subject, how to use Resources plugin in apps and plugins, and how to write customer mappers. If this would be interesting to you please register your interest. The more interest there is, the more likely this will get written!

Recap: What is Resources framework for?

It solves the growing problems around application and plugin static resources. Your CSS, JS and other files have dependencies on each other, and must load in the correct order. You also want to optimize these so that your application loads quickly and caches well for your users.

It provides a way to declare your resources, their dependencies, and a processing chain to modify the resources and response headers to perform all manner of tasks such as bundling multiple resource files into one file, zipping the response, applying long-term client-side caching, or compiling Less or Sass files to regular CSS on the fly.

Where do I start?

First you install the “resources” plugin. To actually see some magic happening you probably want to also install the cached-resources and/or zipped-resources plugins also, but this is not a requirement.

Then you declare some resources in your app, or pull some in from a plugin that supports Resources. Let’s start by declaring a resource that exists in your application, say main.css. To do this you create a file in grails-app/conf/ with a name that ends in “Resources.groovy“. So we might create AppResources.groovy and use the DSL to declare the resource:

View the code on Gist.

This is a module declaration. For full details see the Resources documentation, but in essence this declares a resource module called “common” and it has one CSS resource in it, the file supplied by your application in web-app/css/main.css, and on JS file.

So far, so good. Now you need to pull this resource into a page. To do this requires using some Resources tags.

Using resources in your pages

There are two main tags involved in using resources, with some others that provide extra features. The main two are r:require and r:layoutResources.

The r:require tag tells the framework which resource modules the current GSP requires. The framework will make sure that all the resources declared in those modules are pulled in in the correct order.

To achieve this, you need to include r:layoutResources tags in your <head> and <body> sections. Typically you do this in your SiteMesh layout. You use two calls because one will render the resources that you need to link to in the <head> section of your page (all your CSS, and some of your JavaScript, maybe some favico or iPhone icons). The other goes at the end of the <body> of your page, to render any “deferred” resources, which is usually just your JavaScript code.

So here’s an example of a Grails Sitemesh layout using these tags:

View the code on Gist.

Here you see that you still use the normal Grails sitemesh tags to layout the head and body. These provide the route for you GSP page to actually affect the output, including the output of the Resources plugin’s r:layoutResources tags. That’s because your GSP will call r:require and r:script tags something like this:

View the code on Gist.

This GSP is set to use a Sitemesh layout like the example one given earlier. It uses the r:require tag to say that this page needs the “app” resource module. Using this information, the r:layoutResources tags will render links to all the CSS, JS and other resources of that “common” module, in the correct places.

This means that some may end up in head, and some may end up in body. Remember that we invoked r:layoutResources twice, once in each location? Well, that’s why.

What is this “disposition” stuff?

The disposition of a resource tells the framework which part of the page it belongs – its a form of arbitrary grouping. The default dispositions supported are “head” and “defer” but in fact resources can define any disposition they like – and this can be useful for declaring resources that are not rendered by the normal layoutResources calls (more about this later).

The framework applies a default disposition based on the type of the resource – so CSS always defaults to “head” but JavaScript always defaults to “defer”, so that it runs only when the rest of the page has loaded. Images and icons are also supported to represent favicon and iPhone icons, which render in “head”.

Resource modules usually contain multiple resources and the main reason to specify a disposition when declaring a resource is to force JavaScript to load in the <head> section of the page. To achieve that you just update your resource declaration to include a “disposition” attribute:

View the code on Gist.

Now your page will load with jQuery in the head section, with no code changes to your layout or GSP!

Dependencies

So far, so good but how do we control the order of resources when they are pulled into the page? How can I make sure that my application JS or CSS code always loads after the JS and CSS from a plugin that I’m using?

This is where Resources dependencies come in. There are two simple rules

  1. Resources from a given module are loaded in the order they are defined in the module
  2. Resources from modules are loaded in module dependency order

The first rule ensures that when you declare resources you can intuitively see which CSS or JS loads before another.

The second rule uses the “dependsOn” method in module declarations to list the names of other resource modules on which the module depends. Those will always be loaded before the module that depends on them. Here’s an example declaration that alters our specimen module to depend on the jQuery plugin’s query module instead, and jQuery UI:

View the code on Gist.

Notice that we have specified both jQuery UI and jQuery in the dependsOn. We don’t need to. However notice that they are also declared in the “wrong” order. This is to illustrate that the order you use here is not important – the ‘jquery-ui’ module declared by the Grails jQueryUI plugin depends on on ‘jquery’ (provided by the Grails jQuery plugin) as well – so it will always make sure that is loaded first.

As your application does not define those two modules, you would need to install the Grails jQuery-UI plugin – or define them yourself. Including the jQuery-UI plugin automatically pulls in the jQuery plugin for you, because of Grails’ transitive plugin dependencies. TheResources framework was designed to work hand in hand with the other Grails dependency mechanisms.

So now you have done this, you still have no changes to make to your GSP! It still just requires the “common” module. Notice how this has decoupled your GSPs and layouts from the details of the resources that they need. This is an important feature that gives you great scope to modularise your resources, and even have page-specific modules if you like that contain nothing other than dependencies themselves:

View the code on Gist.

With this, an edit.gsp could just r:require the “editPage” module and never care about the explicit details of what is required.

Dealing with your ugly inline Javascript

You already know that inline Javascript is pretty horrendous, but some things are just plain shameful and yet we can’t help ourselves. Frequently you want to write a Grails taglib that simplifies using a JS library and to do that it must render some code inline when the tag is invoked.

With Resources you can trivially throw this JS code around to wherever you like. You can have the code render in <head> or at the end of the body, and it will automatically do so after loading the resources that the page depends on. To do this you just use the <r:script> tag instead of a normal <script> or <g:javascript> tag:

View the code on Gist.

In this example the script code specified in <head> does not run immediately. The r:script tag also uses “disposition” and the default is “defer” so you will find that the alert only pops up once the rest of the page has loaded, and the HTML source will show the <script> tag at the end of the body, after all other deferred JS code has been pulled in.

All such fragments in the same disposition are concatenated together, so you don’t get a long list of <script> tags.

To force a fragment of inline JS to execute in <head>, just add disposition=”head” to the r:script tag invocation.

To write your own taglibs that generate code in this way, you just output the result of calling the r.script(attrs, Closure) tag from your tag.

Linking to images

Images often need to be optimised or set for long-term caching. However you don’t normally need to declare them in modules. To render images correctly you should use the <r:img> tag anywhere in your pages as you would and HTML <img> tag. All you do differently is supply a uri or dir/file attribute to tell it where to load from. Other attributes are passed through:

View the code on Gist.

That’s all there is to it.

There are however some extra tricks you can pull. Any tag attributes specified in a module resource declaration are honoured when rendering the link. As such this means that you can specify your width & height values if you declare your image – and never have to specify them when rendering links:

View the code on Gist.

Now any r:img links to that logo will automatically include those attributes in the output. Notice that we had to include the disposition “image” which is not a predefined disposition – it is just anything other than “head” or “defer” to prevent the image being rendered by the r:layoutResources tags.

Bundling: combining files to reduce the number of requests

Page load time is a combination of many factors. Those that you can control from your application itself include how many requests are needed to load your page and whether you load resource before or after your HTML content.

To reduce the number of requests made, you need to combine one or more resources into a single file. This is called bundling and what you do is tell Resource which files can be bundled together. This is usually dependent on how your application uses the code, and inevitably requires some compromise.

For example you could bundle all your resources into one file across your entire app – resulting in just one CSS and one JS file for the entire site. With aggressive browser caching this could yield good results, but if you have a few hundred KB of code in these files it could mean it takes a long time for people to see your site the first time they visit or empty their cache.

To specify the bundle that a file belongs to, just add the “bundle” attribute to resource declarations. The Resources framework will not bundle together resources that are incompatible: different content types, or those with differing “attrs”. For example CSS with media=’print’ will not be bundled with screen media.

It does however allow you to bundle resources across module boundaries. This is important as you will see shortly. It also automatically bundles using the module name by default, and maintains separate bundled files for head and defer dispositions automatically.

That is a lot to take in, but it basically means you don’t need to worry about anything.

Just set the bundle attribute:

View the code on Gist.

Here the main.css, which previously might have auto-bundled into bundle “common” if there was more than one resource in the module, will now be bundled into bundle “core”.

The difference has no effect for now, but what you can do is override the module declarations that came from the jQuery plugins and make them go into the same bundle. To do this we use the “overrides” mechanism to change the properties of the resource modules supplied by the plugins. We can call the defaultBundle method to change the default used by them:

View the code on Gist.

Now all the modules will throw their resources together, and you will find your page (again with zero GSP changes) is now pulling in just three files: bundle_core_head.js, bundle_core_head.css and bundle_core_defer.js

Changing how links to resources are rendered

Under the hood, the r:layoutResources tag uses the r:external tag to render links. The r:external tag is a smart tag that writes out the “right kind” of link for a resource. So for JS files it renders <script src=…> tags, for CSS it renders <link href=…>, and so on for favicons and a few other types.

The key thing is that you can pass any other attributes to r:external and they will pass through to the output. It so happens that r:layoutResources pass the “attrs” Map defined in your resource declaration when calling r:external for that resource. This means you can pass any extra attributes you like to the declaration and they make it to the output.

A typical usage for this is to specify media:’print’ on a CSS resource, because the default for this is “screen, projection”:

View the code on Gist.

Note that if you specify these extra properties, those files will not be bundled with others, as by definition this isn’t going to work out well for you.

Wrapping the link in some other code. AKA MS IE workarounds

The resource declaration can also supply some wrapper markup that is used to render the link, with the generated link being passed in as a string. You normally use this to wrap a resource such that it is commented out for all browsers except MS IE:

View the code on Gist.

The wrapper Closure is passed the link text as an argument. You are then free to pre/post-fix it with anything you like.

Linking to specific resources without using the dependency mechanisms

On occasion you may need to link directly to a resource that is handled by the framework, without using r:layoutResources or r:require.

To do this you can use r:resource to get the URL of a resource, or r:external to create a link to it. You can use these to generate absolute links to those resources, for example in an HTML email.

These tags accept the regular uri, url or plugin/file/dir attributes. The r:external tag also supports a “type” attribute to give it a clue what kind of link to render if it is not obvious from the file extension.

Overriding resources from plugins

Plugins that expose modules normally do the right thing, but sometimes you might need to supply different content for a given file, or change some of the tag attributes or the bundle used. To do this you use the overrides mechanism shown earlier in the defaultBundle example.

The “overrides” closure lets you specify new values for some of the module defaults for a given module, but also lets you tweak individual resources if they can be addressed uniquely. Developers must add an “id” attribute to the resource when it is declared for this to work:

View the code on Gist.

This changes the bundle on just the resources with id “js” in the original jquery module. There might be one or more resources with that id in the module. Resources in other modules are unaffected.

For full details of what you can override, please see the Resources plugin documentation.

Using r:require in GSP fragments

Using g:render to render GSP templates to build up your pages is a powerful technique. What you may not have realised is that you can completely modularise these templates now because the enclosing GSP no longer needs to know what libraries they need.

Yes, you can call r:require at any time in GSP rendering – including inside nested GSP templates – and the dependencies of your code will be stored along with your request and the resources all tallied up when the r:layoutResources called in your Sitemesh layout execute.

The only pre-requisite is that your r:require must be invoked before the corresponding r:layoutResources that you’d like to use to render it.

Picture how easy it is now to create portlet-like user interfaces where only the resources needed by UI elements displayed to the user will be loaded, and when they are they will be optimised. The portlets they have not installed or disabled will not load their resources if you do not render their GSP template.

Dynamic requirements

It is important to realise that the r:require tag can support normal GSP EL values in the modules list attribute. This brings great power because you can change the code pulled in by a page at runtime. For example you can make yourself a trivial per-user theme-switching system by storing the name of the theme they want to use in the session, and using a tag like this:

View the code on Gist.

This will locate the theme module and all its dependencies with no further coding.

You could even switch the entire JS library and supporting code used by your plugin’s UI so that, for example, the user could choose between jQuery UI or YUI, or their own implementation.

Including common resources in your layout

Most likely you have some resources that are used in all pages using your Sitemesh layout. This is no problem because you can call r:require inside your Sitemesh layout, with the same proviso as “Using r:require in GSP fragments” – they must be invoked before the r:layoutResources call that would render them.

This means that in practice your individual GSP pages are likely to have only one or two module requirements as the rest is handled by the Sitemesh layout.

Patterns for plugin authors

Here are a few emerging patterns for plugin developers to heed when supporting the resources plugin.

  • Specify id attributes on your resources when declaring them, to maximise the user’s opportunity to override specific details
  • Avoid monolithic modules, opting were possible to separate out functional areas such as the jQuery UI theme being separate from the jQuery UI code. This gives developers more flexibility. Obviously you must maintain correct dependencies between these
  • Put “development” un-minified versions of resources in “<yourmodulename>-dev” modules, so the user can pull in un-minified versions on demand, per-environment if they wish
  • Do not specify the bundling of your modules – at most use defaultBundle. No per-resource bundle attributes. Let the developer control this easily by overriding your defaultBundle settings in each module.
  • Use module names prefixed with the name of your plugin followed by a hyphen i.e. “jquery-main”, “myplugin-theme”, “acmeplugin-ui-styling”

Summing up

All the things we’ve tackled here are core Resources framework features – no extra plugins are required. The resource mapper that performs bundling is even built into the framework.

The real fun starts when you install some of the other mapper plugins – they may be renamed, re-encoded or even compiled from one form into another. It all happens at startup for declared resources, and at runtime for ad-hoc resources. Once it’s been done it is stored on disk on the server in that state and no more processing is done.

I hope you have fun with the Resources framework!

There are some nice refinements and maybe some new features coming in point releases at the time of writing.

31 Comments

  1. allnightlong
    September 13, 2011

    Hi, Marc. I’m really like your resource plugin. But there is one thing I can’t get.
    On my production servers, my static files are served by nginx, not tomcat. Static files stored on different domain (static.mydomain.com). To assist me manage files in development/production environments I’m using old static-resources plugin (http://grails.org/plugin/static-resources), which is no longer maintained . I’m want to migrate to resource plugin, but I didn’t find the way to change domain in different environments. Also, there is not built-in webserver, so I’m a little bit confused.
    Any help here would be appreciated.

  2. Marc Palmer
    September 13, 2011

    The static-resources plugin is a completely different beast.

    To serve your resources from another daemon and domain, for now you will need to:

    * Set the work dir for resources via Config (see docs) to point to a permanent dir on your server
    * Mount that dir as static.mydomain.com as a vhost or equivalent
    * Use mod_proxy or equivalent to rewrite the yourapp/static/xxxx links to static.mydomain.com

    This is just until we add support for specifying an alternative base url for your resource links per-environment.

  3. allnightlong
    September 13, 2011

    Thanks for your answer.
    I’d found corresponding jira issue http://jira.grails.org/browse/GPRESOURCES-16 .
    It’s about year old, and currently there are not any progress on it. Are there any tentative dates on this issue?

  4. Marc Palmer
    September 13, 2011

    There are no tentative dates, sorry. I am not paid to work on this, so its a case of me chipping away when I can at all the stuff I work on. I will try to get to it soon. I’m also working on a plan to fund some of this work…

  5. Kaleb Fulgham
    September 13, 2011

    I happened to be looking through the Changelogs for Grails 2.0-M2 and ran across the following improvement fix & suggestion. http://jira.grails.org/browse/GRAILS-4374

    Graeme says, “static resource loading can now be configured by supplying a grailsResourceLocator bean that is an extended instance of CachingGroovyPageStaticResourceLocator”

    Looks nifty

  6. Alfonso Rivero
    September 19, 2011

    Hi Marc,

    Nice and usefull plugin. I’m playing with it and I haven’t found how to change the theme in combination with the jquery-ui plugin.
    It should be very easy, but I haven’t been able to do it.

    Thanks

    Alfonso

  7. Marc Palmer
    September 19, 2011

    To change the theme with the jQuery UI plugin you need to use module overrides on the jquery-theme module, to replace the css file that pulls in with your own.


    modules = {
    overrides {
    'jquery-theme' {
    resource id:'theme', url:[your-url-info-here]
    }
    }
    }

  8. Alfonso Rivero
    September 20, 2011

    Thanks for your answer.

  9. Robert
    September 20, 2011

    Is there a way to tell it to use the old format? in other words I used to use createLink, which got deprecated to resource, but resource wants to put in that ‘static’ in the url, which screws up all my links.

    I can’t seem to remove it from the config either. putting in ” for the prefix gives me something like context//file.html instead of context/static/file.html.

    In my case “file.html” is a custom url mapping and not a physical file.

  10. Marc Palmer
    September 20, 2011

    Robert I’m not quite clear what your problem is. Can you give a clear use case please?

    If you don’t want to use resources plugin just uninstall it. If you do, you need the /static/ prefix there for it to work. You can set the adhoc exclude patterns config variables (see doc) to exclude e.g. **/*.html if you need to.

  11. Sébastien Blanc
    September 28, 2011

    Hi Marc,
    Thanks for this entry, it’s a great source of inspiration.
    Just one question about deferring javascript : The resources nicely put my js (both libs and inline) at the end of body but it’s parsed before the page is rendered (I added a Alert() in my inline js to be sure).
    My first thought was that it was because of the sitemesh layout (parsing the js present in the layout before rendering the entire page)but it’s not the case.
    Do you have any idea ?
    Thanks

  12. Marc Palmer
    September 28, 2011

    Sébastien – without seeing your output I cannot be sure, but this sounds like it is browser dependent.

    The script loads at the end of the body, so if the browser does not yet believe it can lay out your page, it will not do so before the alert shows.

    Trace through your JS and you will see when it executes. However this does not mean the browser has rendered your page yet. Welcome to web hell :)

  13. Migrating from the Grails UI-performance plugin to resources plugin. | Tomás Lin’s Programming Brain Dump
    October 21, 2011

    [...] of the posts on the web ( like this one, or this one )describe how to get started with the Resources plugin from scratch. However, chances [...]

  14. Marko
    December 17, 2011

    Hi Marc,

    Some of your links to code snippets are invalid (Chrome, iPad, ???). For example: https://gist.github.com/1211561.js?file=resources_article_1_snippet_5.groovy

    Nice helpful post :-)

    Marko

  15. Marc Palmer
    December 17, 2011

    Hmm yes, seems there is a problem with the gist plugin for wordpress

  16. Marc Palmer
    December 17, 2011

    FYI I’ve fixed them now. Thanks for pointing it out.

  17. Trygve
    March 24, 2012

    Thanks Marc! I was looking for information on this subject, and this is great! Regards.

  18. Rajesh
    May 12, 2012

    Hi all,

    For others’ benefit – Just thought of mentioning that the “resources” plugin breaks the richui 0.8 plugin in Grails 2.0.1. To get around the problem I added the following line to the Config.groovy -

    grails.resources.adhoc.excludes = ["/plugins/richui-0.8/*", "/plugins/richui-0.8/**"]

    Regards
    Rajesh

  19. ab
    May 23, 2012

    Is it possible to have similar kind of module structure in Spring MVC?

  20. ab
    May 23, 2012

    Hi all,
    Is there any similar kind of module structure available in spring MVC?

  21. Sikander
    June 27, 2012

    This is a very good post and a well explained use of plugin. The plugin is kinda cool because it will help in removing the mess of added JS or CSS files.

    Good work.

  22. Panche
    July 16, 2012

    Thanks Marc for the great plugin.

    Howeever I expirienced a huge problme with this plugin using grails 2.0.3 and multiple application instances.
    They were run with grails run-app from multiple directories and both end-up copying resources in .grails/project dir so when I run the first instance and then grails clean; grails compile the secind instance the resources got messed up.

    Please refer to this lin for more detailed explanation:
    http://stackoverflow.com/questions/11328108/grails-2-0-missing-resources-when-running-multiple-instances

  23. Marc Palmer
    July 26, 2012

    You need to set a unique grails.resource.work.dir config value in each app. See the config docs.

  24. Marc Palmer
    July 26, 2012

    No, this is a Grails plugin.

  25. Adrian Rodriguez
    October 10, 2012

    Hi,

    Just say, excellent information. this help me a lot.

    thanks,
    Adrian

  26. Derryck See
    December 6, 2012

    Hey Marc,

    I’m trying to create a web page that would send a gsp template, that uses a resource module from StaticResources.groovy, as an email. However, a parsing exception is thrown on every attempt to send the gsp template as an email; the only way I got it to work was to use g:external tags instead of the resource tags. So, I was wondering, is there anyway to send a gsp template, that uses a resource module from StaticResources.groovy, as an email?

    Thank you,

    Derryck See

  27. Marco
    December 6, 2012

    Is it possible to use something like a wildcard to include all the script in one folder?

    example “/js/module-a/*.js”

  28. Marc
    December 13, 2012

    Hey Marc,
    wer are using your plugin in our current project,
    im on the frontend and have no idea to get my images running with oneline – for now they are like so:

    resource url:’images/Beirat/ruerup.png’
    resource url:’images/Beirat/herholz.png’
    resource url:’images/Beirat/ehlers.png’
    resource url:’images/Beirat/bausch.png’
    resource url:’images/Beirat/albath.png’
    resource url:’images/Beirat/blitzer.png’
    resource url:’images/Beirat/klewes.png’

    can you tell me how to achieve this? best regards.

  29. Marc Palmer
    December 19, 2012

    Why are you declaring your images? There’s no need to unless you want to use them as e.g. iphone icons or to specify the width/height.

    Most people do not bother. There is no way to batch register resources currently, but you can write code in the DSL to do this using java.io.File and groovy’s eachFile.

  30. Marc Palmer
    December 19, 2012

    No, not at this time

  31. Marc Palmer
    December 19, 2012

    Resources requires an active request. This *should* work for mail but it seems like there is something wrong with the mock request. Without full details I can’t say any more.

    FYI I’m closing comments on this post – this is not a support forum!

    Please use the grails user mailing list for support and/or raise jira issues at jira.grails.org/browse/GPRESOURCES for specific problems with details.