My current project is a single-page Grails application that contains a lot of static resources. I’m using the standard Resources plugin and have found myself spending a lot of time keeping the plugin’s config file in sync with my application’s files. I want to try to minimize this hassle by using convention where I can.
Here is an example of how my configuration is set up.
The is a contrived example, but it is very similar to the one I am currently using. As you can see, there is one core module at the top and then a module for each domain. Each module contains a mix of CoffeeScript, LESS, and Handlebars.js templates. Note the dummy.css files at the end of each module. These are here to make sure the plugin bundles the LESS files properly, see this bug.
The first thing I want to do is try to convert some of these calls to use Ant paths so I don’t have to explicitly declare each file. It turns out that this is not supported by the Resources plugin directly. There is a Jira issue here with a similar request, but it’s over a year old.
Since the config file uses Groovy, we can add support ourselves by creating a function that will locate the files. With the help of this stackoverflow post, I’ve created a function that will create a Set of files similar to the behavior of Ant‘s fileSet.
This will find all the files in the given directory matching the includes pattern. I’ve put this method into a util class and imported it into the config file. Now applying the method to the existing configuration yields this.
Note that I didn’t apply the fileSet method to anything in the core module, because it cares about the file order. We can apply it to the other modules, though, and now the file is shorter and requires less maintenance. But there is still another step we can take.
You may have noticed that the domain modules in the configuration all follow the same pattern. Handlebars files in ‘/templates/$domain’, LESS files in ‘/css/app/$domain’, etc… Once again we can use Groovy to help us by adding a closure to create a common module template.
After applying this to our config, we now are left with this.
This greatly simplifies our configuration and makes the structure of our files more obvious.
One caveat with this approach is that adding new files will not trigger the Resources plugin to reload the modules. It only watches files that are included when the config is parsed. One way to add this functionality is to create a DirectoryWatcher in BootStrap.groovy.
This is not perfect as it will reload all modules, not just the affected ones, so there is still some room for optimization.
With a few lines of Groovy, we’ve made our config file more maintainable, simplified our development process a bit, and created a template that will help make sure our application’s resources continue to follow a logical pattern.
A working example app can be found here.