Project

General

Profile

BrowserCaching » History » Version 4

dj jones, 2014-09-01 15:38

1 1 dj jones
h1. BrowserCaching
2
3 2 dj jones
h2. General Background: as to why caching in browser is a good thing
4 1 dj jones
5
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.
6
7
(This in general means files like:  .css, .js and image files)
8
9
But some content does change very fast, so must not be cached by the browser.
10
11
*If the browser is told 'don't cache this object':*
12 4 dj jones
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.
13 1 dj jones
14
*But in the absence of that - if the browser is not sure about a page component*
15 4 dj jones
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.
16 1 dj jones
17 4 dj jones
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.
18 1 dj jones
19 4 dj jones
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.
20 1 dj jones
21
*So we need to tell the browser that these objects will not be stale for a long time*
22
23
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'.
24
25 4 dj jones
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.
26 1 dj jones
27
The users experience faster web page builds!
28
29
h2. The Problem with Redmine
30
Unfortunately, RedMine also uses .js file names, for things that DO content user content:  ie things that should NOT be cached in the browser.
31
32
So this means;  if in Apache/nginx you add a simple config, to cache anyting that is named *.js:   then your Redmine will break!
33
34 3 dj jones
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.
35 1 dj jones
36
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
37
38
h2.The work round for RedMine
39 3 dj jones
40 4 dj jones
Is to use a more complex configuration:  that also checks which directory the .js file is in, before setting the cache heading.
41 1 dj jones
42
Etienne suggested this nginx configuration  (see Issues #13564):
43
44
<pre>
45
location ~* ^(?:(?:plugin_assets/|themes/).+/)(?:javascripts|stylesheets|images)/.+\.(?:css|js|jpe?g|gif|htc|ico|png|html)$ {
46 4 dj jones
expires 365d;
47
}
48 1 dj jones
</pre>
49
50
The simple case, that will break Redmine, does not care about which directory eg:
51
<pre>
52
location ~* \.(ico|css|js|gif|jp?g|png)(\?[0-9]+)?$ {
53
expires 365d;
54
}
55
</pre>
56 4 dj jones
57
Note that in nginx:  'expires' is the config that sets the 'Expiry' HTTP header in the object.
58
59
In the above, 365d means 365 days.
60
61
See nginx page:   http://nginx.org/en/docs/http/ngx_http_headers_module.html#expires