Webjars on the Asset-Pipeline, Perhaps Someday

Posted by David Estes on Apr 11, 2014

Filed under Grails

So I looked at web jars last night, and the existing resources plugin implementation via. The modules-manager.

The file publication mechanism introduced in the Servlet API 3.0

This argument is actually completely invalid for the grails ecosystem. If you read the source code for the modules manager plugin that exists today you can see that here. The plugin essentially, Unzips the jar file and copies the files (eventually) into web-app/modules. Then it creates a ModulesResource.groovy file to contain the bundle names and this is where other specifications get kinda hairy.

Asset Resolution

Currently, per the WebJar documentation , it seems to prefer to use a require.js structure to load its assets and again the existing Grails support omits this and simply allows access to the static assets. However even this is sorta brittle. Since there is no formalized structure for the asset naming within the file the resources module tries to exclude certain patterns:

patternset excludes: "**/*.min.css **/*.min.js **/*-min.css **/*-min.js"

This right here also becomes a problem , for example ember packages an ember.prod.js and even an ember.debug.js, Or handlebars has handlebars.runtime.js. Determining a package structure by simply excluding min related files is not really reliable.

Then lets say we did fix Asset-Pipeline to be able to find files on the META-INF/resources class path. Ok lets look at what that might potentially look like in an application.js manifest

//=require webjars/jquery/2.1.0/jquery

console.log('Hello World');

Instead of making something clean like:

//=require jquery

console.log('Hello World');

So now we have to deal with the version number being in the class path. This makes just simply updating your BuildConfig problematic, because now you've lost your file reference. Now if, in a webjar file existed a jquery.js at the root say META-INF/resources/webjars/jquery.js We could potentially let that file contain this:

/*
This is an asset-pipeline manifest reference file.
*/
//=require jquery/2.1.0/jquery.js

This would allow us to use jquery more simply in our asset-pipeline:

/* Example application.js */
//=require webjars/jquery

Thats much better to use from a developer experience perspective. However, with webjars in its current form that is not really feasible.

So could someone make a plugin that allows webjars to work in your application like the resources module does. Yes, you could make a gant script like grails refresh-modules that unzips those files and places them in grails-app/assets (Essentially what that module does only in web-app/modules). But its not really an elegant solution and feels like more of a hack. And that isn''t even the fault of the developer who wrote the plugin, Considering the confines of the resources plugin this is definitely the best solution I could see being done.

The other concern I have and @jamesward could give more insight into this who has done a great job maintaining the webjars library. Most of the webjars listed on the website point to Github repositories within the webjars organization. A lot of which are forked from former maintainers who no longer maintain the plugins. This implies a lack of community support on maintaining a lot of these various plugins, so the question then becomes is this work worth the effort?

So to summarize, the argument for servlet 3 API is not really valid in any of these situations. A clean way to define modules and file requirements (outside of requirejs) does not exist in the webjars specification. The webjars ecosystem appears relatively new and is still evolving. Would we like to allow asset-pipeline to scan the META-INF/resources classpath? Sure, definitely need to put that on the road map. But I'd rather do it right and not hack it which takes a lot of time and effort. This is not a "design-problem" with the asset-pipeline as it works EXACTLY how it was designed and intended to be used. If @jamesward can help determine a way to list files in a manifest that can be cleanly parsed without needing a require js module (because we know Java js runtimes are still fairly slow and Nashorn is relatively new). I'd be happy to look into it then. Until then, I would recommend (Bower)[http://bower.io/] As an alternative means at maintaining client side dependency trees.