How to force browser to not cache css file when the css file changes?

347 Views Asked by At

I have a base layout file which is used in most of the views. In the base layout i require a module using the grails resources plugin.

<r:require module="core"/>

The modules are defined in conf/ApplicationResources.groovy file as

modules = {
    core {
        resource url: '/css/main.css'
        resource url: 'js/application.js'
    }
}

Now here is the problem. I make change to main.css file and build the app. The change doesnt reflect in the browser. It will only update if i view source and then click on css file and then refresh that css file. The browser caches the css file. I have tried appending version to the above code like

modules = {
    core {
        resource url: '/css/main.css?version=2'
        resource url: 'js/application.js'
    }
}

but this also doesn't work. When i look at the generated css link tag i see that the css file is

<link href="/app/static/bundle-bundle_core_head.css" type="text/css" rel="stylesheet" media="screen, projection" />

So it makes sense why version is not working. I have tried as a last resort

<link href="/app/static/bundle-bundle_core_head.css?version=2" type="text/css" rel="stylesheet" media="screen, projection" />

and the css file was finally updated. But I cannot use this solution since that was a hack.

So my question is is there a way for the css file to automatically update when i make a change to the css file while using the grails resources plugin.

Resources Plugin

http://grails.org/plugin/resources

The grails version I am using is 2.2 and the resources plugin version is 1.1.6.

2

There are 2 best solutions below

1
On

If you use an Apache webserver, you can use an .htaccess file. Specifying the file concerned, it won't be cached.

<Files main.css>
FileETag None
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</Files>
0
On

A pragmatic approach (if all aproaches fail) could be to change the name of the CSS files that have changed (e.g. bundle-bundle_core_head_vjfiduht.css). That way the browser does not recognize the file and definitely tries to load it.

On the other hand: in prod the resources plugin should use a hash value for the name of delivered resources (given that you haven't turned it off via grails.resources.mappers.hashandcache.enabled = false.