3

We're trying to force the client's browser to reload static files when they change. Currently, we have our build scripts automatically creating a new directory with the build timestamp and replace the content in the code to point to that directory.

However, I feel this is hardly an optimal solution. It forces the client browser to load every single file if a new build exists, even if only 1 file changed, and build time increases considerably by scanning every file and replace every static file reference.

I know we can also set the version when we declare files (something like < link src="blahblah.css?version=1.1" />), but this forces us to change all our code to include a version placeholder and still have our build scripts replacing it.

Is there a smarter way to do this? We're using Spring MVC. Is there any option in mvc:resources that I'm not aware of to do this without changing code? Or something on web.xml?

We're using tomcat. Is there a way to do this at server level? Would it help to use a cache like Varnish or something? Or these caches only allow to set expiry times and not check that the file changed? Bear in mind I'm not comfortable at all in server and cache configuration tasks.

I found out about this project https://code.google.com/p/modpagespeed/, but since it's far from my comfort zone, I'm struggling to understand capabilities and if this helps with what I want.

Anyone has any ideas? Thanks

redwulf
  • 1,317
  • 3
  • 13
  • 35

2 Answers2

2

You can use version as a query parameter, e.g. /resources/foo.js?_version=1.0.0. If you are using Maven, it is not that hard to get version information from /META-INF/maven/{groupId}/{artifactId}/pom.properties. Of course this will force reload all scripts with every new version... but new versions are probably not deployed that often.

Then it is always a good practice to properly set HTTP caching headers. <mvc:resources> should correctly handle Last-Modified header for you. And you can set cache-period to make browser check the for resource modifications more often.

Pavel Horal
  • 17,782
  • 3
  • 65
  • 89
  • I was avoiding to use query parameters, since that forces me to change my code to include a placeholder for maven to replace. It also forces to pollute code with the versioning, which I feel is a cross-cutting concern that shouldn't be hardcoded in all my files (of course I'll do it if I can't find any other way). The Last-Modified header with mvc:resources seems to be what I want. I'll give it a try. Thanks – redwulf Aug 28 '14 at 08:17
  • Query parameter does not require maven to process anything. You can read version information at runtime and set it as request parameter (or add EL function for that), no resource filtering is required. If you dont want to have `` in your templates, you can implement url rewriting. I would not suggest hardcoding as a solution :). – Pavel Horal Aug 28 '14 at 08:21
1

Here is a working solution: CorrectBrowserCacheHandlerFilter.java

Basically, when your browser requests the static files, the server will redirect every requests to the same one but with a hash query parameter (?v=azErT for example) which depends on the content of the target static file.

Doing this, the browser will never cache the static files declared in your index.htmlfor example (because will always received a 302 Moved Temporarily), but will only cache the ones with the hash version (the server will answer 200 for them). So the browser cache will be used efficiently for those static files with hash version.

Disclaimer: I'm the author of CorrectBrowserCacheHandlerFilter.java.

Anthony O.
  • 22,041
  • 18
  • 107
  • 163