Project

General

Profile

Actions

BrowserCaching » History » Revision 8

« Previous | Revision 8/19 (diff) | Next »
dj jones, 2014-09-01 15:46


BrowserCaching

General Background: as to why caching in browser is a good thing

It is good practise on any website to let the browser cache objects that are static - ie don't contain user content, and are the same for hours, days or weeks.

(This in general means files like: .css, .js and image files)

But some content does change very fast, so must not be cached by the browser.

If the browser is told 'don't cache this object':
then it knows not to. This is what Websites (and Redmine) do on the pages that may change: eg an issue page: it will put into the HTTP header that message.

But in the absence of that - if the browser is not sure about a page component
that it already has recently downloaded, it will send a 304 request to the server: saying 'can you tell me, is this file still not stale'. And with a 304 the server does not need to send the whole object again: just a short 'yes, that is still fresh' answer.

In Redmine's default set-up: it generates a lot of 304 connects on every page: you can see these in a tool like Firebug. One for every css and .js file etc. Many.

These are bad for the user experience: because the browser has to wait for these responses, before it can carry on and build the page.

So we need to tell the browser that these objects will not be stale for a long time

There are easy ways to configure Apache and nginx to do this: by telling them to set the 'Expiry' date in the HTTP Header well into the future: so that the browser knows: OK, this objects is not stale, because we are still before the expiry date'.

Thus when a new user visits Redmine, their browser on the first page will GET the .css and .js files etc, but on pages after that: does not need to get them again.

The users experience faster web page builds!

The Problem with Redmine

Unfortunately, RedMine also uses .js file names, for things that DO contain user content: ie things that should NOT be cached in the browser.

So this means; if in Apache/nginx you add a simple config, to cache anyting that is named *.js: then your Redmine will break!

See the Issue #17770 - where this problem is reported, to see if the RedMine team can change RRedmine, to STOP using the .js in bad places.

Tne places it breaks if you use a simple config are: (a) when editing a journal in an issue (b) when uploading a file to an issue

The work round for RedMine

Is to use a more complex configuration: that also checks which directory the .js file is in, before setting the cache heading.

Etienne suggested this nginx configuration (see Issues #13564):

location ~* ^(?:(?:plugin_assets/|themes/).+/)(?:javascripts|stylesheets|images)/.+\.(?:css|js|jpe?g|gif|htc|ico|png|html)$ {
expires 365d;
}

The simple case, that will break Redmine as above, because it does not care about which directory the js files are in:eg:

location ~* \.(ico|css|js|gif|jp?g|png)(\?[0-9]+)?$ {
expires 365d;
}

Note that in nginx: 'expires' is the config that sets the 'Expiry' HTTP header in the object.

In the above, 365d means 365 days.

See nginx page: http://nginx.org/en/docs/http/ngx_http_headers_module.html#expires

Updated by dj jones over 9 years ago · 8 revisions