Don't Overwrite Plugin Assets with Your Own

December 13th 2015 Grails Asset Pipeline

Grails web application framework does a great job at taking care of the plumbing, without the developer having to know about all the details until he needs to customize it in some way. Grails Asset Pipeline plugin follows the same general approach in doing the processing of static assets, such as JavaScript and CSS files: transpiling, minimizing and bundling them.

However, not knowing about the implementation details can become a problem, when troubleshooting issues that arise because of them. I just stumbled across such an issue related to assets being distributed with a Grails plugin. Something was causing that not all of them were correctly referenced from a GSP page.

To make development easier, Grails Asset Pipeline supports special syntax for referencing related files from a common manifest file; e.g. one can create a single JavaScript file referencing a framework such as AngularJS and some of its modules in correct order:

//= require angular/angular.js
//= require angular/ngStorage.js

To reference all of these files (either unchanged during development or minimized and bundled in production) only a single tag needs to be added to the view (angularManifest.js is the name of the above manifest file in this case):

<head>
  <asset:javascript src="angularManifest.js" />
</head>

As long as all of these assets are included directly in the Grails application, it's easy to stay on top of the manifests and the included asset files. When they originate from a Grails plugin installed in the application, it gets much harder. In our above example, the manifest file and the files it references could all be coming from a plugin, instead of being directly included in the application. While this makes it easy to maintain a common set of assets used in several applications, there's no way to see which files are actually included in the plugin. Again, in most cases this doesn't matter: all files can be referenced via a single common manifest file if the plugin has one.

The problems arise when an asset in the application has the same name and path as the one in the plugin, e.g. we could create a different angularManifest.js in our application:

//= require angular/angular.js
//= require angular/ng-file-upload.js

This file would override the one coming from the module, causing ngStorage.js not being referenced from our views any more. Although I can imagine scenarios in which such overriding could be useful, it can also introduce bugs which are hard to detect and troubleshoot. Keep that in mind when creating plugins with assets and organize the assets in a specific enough way to prevent accidentally overriding them in the application.

Copyright
Creative Commons License