Gangmax Blog

自由之思想,独立之精神

Expose Static Resources in Grails

| Comments

Recently, I’m working on a project in which I use Grails to implement RESTful API back-end with the “rest-api” profile. It’s simple and works well, until the frond-end developer asks me to intergrate the front-end implementation(React with “javscript/css/font/image”) files into the back-end Grails project.

The problems are:

  1. How to expose the static resources(“javscript/css/font/image” files) in a Grails project to make it available directly to the browser without the controller handling?

  2. How to integrate the “index.html” of the React application into Grails?

It tooks me several hours to find the answers. Here is the solutions.

Solution for problem 1

From here, here, here, here and here.

  • First, put the static resources files(including “index.html”) into the “src/main/webapp/” directory. After doing so, when packaging the Grails project into “war” file, the content in the “src/main/webapp/” directory will be packaged into the “war” file under the root path.

  • Second, in the “UrlMappings.groovy” under the “controllers” directory, add the following content to declare the static resources are NOT handled by controller:

UrlMappings.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class UrlMappings {

    static excludes = [
            '/css/*',
            '/fonts/*',
            '/static/*',
            '/asset-manifest.json',
            '/favicon.ico'
    ]

    static mappings = {
        ...
    }
}

According to the Grail official document, after the 2 steps above, the static resources should be available for the browser. However it did not. The following steps took me a lot of time to find out from here.

  • Update the “conf/application.yml” by adding the following content:
application.yml
1
2
3
grails:
    resources:
        pattern: '/**'

Without this configuration Grails exposes all the static resources under the “/static/” path, with the configuration the static resources will be exposed under the “/” path, which is what we want.

Solution for problem 2

From here, here and here.

  • Create a new controller
RootController.groovy
1
2
3
4
5
class RootController {
    def index() {
        redirect(uri:"/index.html")
    }
}
  • Route the “/” path to the new controller
UrlMappings.groovy
1
2
3
4
5
6
7
8
9
10
11
12
class UrlMappings {

    static excludes = [
        ...
    ]

    static mappings = {
        ...

        "/"(controller: 'root', action:'index')
    }
}

Then when you access the root path of the web application, the “index.html” content will be returned.

Notes:

  • I tried to make the “index.html” as part of the static resources to make it available, but then I found it’s not a good idea, the reasons are:

    1. The URL of root domain cannot be redirected to “index.html”, which means “http://test.com” is not available but only “http://test.com/index.html” is;

    2. Even if using “http://test.com/index.html”, after some content on the page is changed, refreshing does not work since the “index.html” is treated as “static resource” which means it’s cached in the browser.

    So the “index.html” content must be handled as danymic content by controller.

Comments