Asset-Pipeline 2.0

Posted by David Estes on Dec 03, 2014

Filed under Grails, Open Source

Finally, after over 6 months of work, we are ready to announce the new Asset-Pipeline plugin for the JVM. As many people already know, the Asset-Pipeline plugin started out as a Grails plugin to replace the aged resources plugin. The plugin provided on-the-fly compiling of assets during development (including transpiling coffeescript, LESS, SASS, Handlebars, and more) for easy debugging. It also provides a rock solid build phase for serving compiled assets in a clean packaged production war or jar with their proper ETag, and Cache Headers.

Now it's time to bring these things to the JVM web community as a whole. This involved a major refactoring of how asset resolution was performed and configured. The core of the asset-pipeline was split into a library called asset-pipeline-core. This plugin provides all the core classes necessary for interacting, resolving, and compiling static assets. It does not, in and of itself, implement ServletFilters nor view helpers directly. This has intentionally been left out to make it more agnostic to frameworks on the web. Instead we now have add-on libraries that provide this functionality scoped to the relevant framework. The first of which is called asset-pipeline-gradle.

Gradle !!

Gradle is a rock solid build tool on the jvm that pretty much everyone should start moving to. It leverages a clean groovy language DSL to make for easy configuration of your project builds. Thanks to the Asset-Pipeline we can now easily compile assets in our assets/**/* folder down into the build/assets folder. So if you just want to keep your client side assets outside of your server framework or dump these assets into a non-supported framework you can use this plugin to do so.

The plugin provides 2 important tasks assetCompile, and assetClean. It also provides a means to configure the behavior. This includes minification options, exclusion/inclusion rules, configOptions for extension modules (like less-asset-pipeline). You can see this in action in the Readme of the core plugin here

Compile All the Things!


  • Bundling
  • Minification
  • Transpiling Coffee, LESS, Handlebars, SASS, and more.
  • SourceMaps
  • Easier Debugging
  • 2x Performance Improvement
  • ECMAScript 6 to ES5 transpiling
  • Custom File Resolvers

So whats so cool about this asset-pipeline thing anyway? Most of those UI devs already seem to like using Grunt or the new Gulp hotness. First off, have you seen what it looks like to configure these tools? It's pretty darn ugly. But works well with node.js and node provides a lot of tools for transpiling these web based assets. The JVM can be just as good at transpiling assets, if not better in some cases. And, in some cases, we can even leverage the node.js libraries to accelerate compilation of assets like coffeescript.

Another great aspect of the asset-pipeline library is it's extensibility. It is very easy to add custom file specifications known as AssetFile implementations. Simply define one of these and specify the content-type, source extension, compiled extension, and any processors you want to run on the file and thats it. Want to automatically handle .coffee files? Simply add to your class path. Same with LESS or with Handlebars. Even compile SASS files in the very near future (working on it). Or use some great tools from @craigburke1 for Angular.js files. Finally we have a standardized way to add extensions to the jvm (like node does) with which we can process our web assets.

With the release of the new asset-pipeline, I mentioned earlier that there was a lot of refactoring of how assets were resolved. The core plugin provides two AssetResolver Implementations. They are called the FileSystemAssetResolver and the JarAssetResolver. Resolvers can be registered with the AssetPipelineConfigHolder and they will be scanned in order of registration. This allows a framework implementation to specify where their assets are stored, even in binary plugins if they want. Requiring one js file into another js file is the same as it was before:

* Example application.js manifest file
//= require jquery
//= require_tree .
//= require_self

console.log('Example File Manifest');

If all those features weren't enough for you, there are still benefits to using the asset-pipeline. Even if you use gulp and grunt you can still use these tools (and yes you can use bower with this). Even just dumping your bundled assets into the asset-pipeline resolver path provides benefits for final packaging of your application. During the assetCompile phase your assets are gzipped, given digest names, and a manifest is generated for ETag headers and CDN syncing. The core plugin provides a helper class for use by framework implementors in finding files based on the incoming web request and setting the appropriate response headers. It automatically, creates great CDN support as well as leverages E-Tags to minimize excessive serving of assets.

Framework Support

Of course, the first web framework being supported will be Grails (as far back as grails 2.2.0). These plugins are on their way out the door and will be hitting the world wide web shortly. Not only are we supporting the grails framework, we are also experimenting with Spring Boot support which can be found in the main asset-pipeline-core repository. Gradle standalone is also supported if you want to try out compiling assets into your other framework implementation. We are looking to prioritize support for Ratpack as well. There are many jvm based web frameworks out their now, and many of which could leverage the libraries provided by the asset-pipeline plugins. Extending this plugin to add additional file types can be done once, and automatically made available to all the frameworks leveraging this plugin's ecosystem.


We of course welcome any contributions and feedback as we continue to develop and enhance this suite of libraries to make web development on the JVM clean, concise, and easy. Pleae feel free to check out the Asset Pipeline Repository for more links to resources and example uses.