Search code examples
grailsassetsgsppipelineinject

Grails: render file from assets folder into gsp


I use require.js in a Grails project. There are a couple of single JavaScript files containing the require.js modules defined with define.

There is also a *.gsp file which generates the require.js config and the entry point starting with require() as there is some dynamic configs to be generated. It looks somehow like this:

<%@ page contentType="application/javascript;charset=UTF-8" %>

require(['a', 'b'], function(a, b){
    ...
    var a = ${controllerPropertyA};
    ...
    some functions        
    ...
});

In my layout I integrate require.js like this:

<script data-main='http://example.com/exampleController/dynamicGenerateMethod?domain=xyz.com' src='http://example.com/assets/require.js'></script>

All the modules a , b, and so on are asynchronously loaded by require.js. Now I would like to bundle them into a single file - I could use the require.js optimize tool but I prefer to use the assets-pipeline. This works as far as that I get all modules bundled into a single optimized-modules.js which is available on http://example.com/assets/optimized-modules.js.

The question: I would like to have the optimized JavaScript code in the dynamically rendered GSP file. So how can I inject the optimized-modules.js file into the GSP I'm dynamically rendering? I already thought about a tag defined in the tag library so that my *.gsp would look like

<%@ page contentType="application/javascript;charset=UTF-8" %>

<g:renderFile file="/assets/optimized-modules.js" />
require(['a', 'b'], function(a, b){
    ...
    var a = ${controllerPropertyA};
    ...
    some functions        
    ...
});

and the tag definition somehow like that:

    def g:renderFile = { attrs, body ->
        def filePath = attrs.file

        if (!filePath) {
            throwTagError("'file' attribute must be provided")
        }
        //out << filePath
        out << request.servletContext.getResource(filePath).file
        //out << grailsResourceLocator.findResourceForURI(filePath).file.text
        //out << grailsApplication.mainContext.getResource(filePath).file.text
        //out << Holders.getServletContext().getResource(filePath).getContent()
        //IOUtils.copy(request.servletContext.getResourceAsStream(filePath), out);
    }

But I can't get the content of the minified optimized-modules.js which was done by the assets-pipeline plugin on startup. Any thoughts on this?


Solution

  • Ok, I finally found it out by myself:

    Instead of using the grailsResourceLocator I had to use the assetResourceLocator which is the way to go if you try to access assets resources.

    My tag definition now looks like:

        def renderFile = { attrs, body ->
            def filePath = attrs.file
            if (!filePath) {
                throwTagError("'file' attribute must be provided")
            }
            ServletContextResource bar = (ServletContextResource)assetResourceLocator.findAssetForURI(filePath)
            String fileAsPlainString = bar.getFile().getText("UTF-8")
            out << fileAsPlainString
        }
    

    That way I can inject a compile assets javascript file into my GSP - perfect!