BrowserCaching » History » Version 1

dj jones, 2014-09-01 15:33

1 1 dj jones
h1. BrowserCaching
2 1 dj jones
3 1 dj jones
H2. General Background: as to why caching in browser is a good thing
4 1 dj jones
5 1 dj jones
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 1 dj jones
7 1 dj jones
(This in general means files like:  .css, .js and image files)
8 1 dj jones
9 1 dj jones
But some content does change very fast, so must not be cached by the browser.
10 1 dj jones
11 1 dj jones
*If the browser is told 'don't cache this object':*
12 1 dj jones
 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 1 dj jones
*But in the absence of that - if the browser is not sure about a page component*
15 1 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 1 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 1 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 1 dj jones
*So we need to tell the browser that these objects will not be stale for a long time*
22 1 dj jones
23 1 dj jones
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 1 dj jones
25 1 dj jones
Thus when a new user visits Redmine, their browser on the fisrt 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 1 dj jones
The users experience faster web page builds!
28 1 dj jones
29 1 dj jones
h2. The Problem with Redmine
30 1 dj jones
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 1 dj jones
32 1 dj jones
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 1 dj jones
34 1 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 1 dj jones
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 1 dj jones
38 1 dj jones
h2.The work round for RedMine
39 1 dj jones
Is to use a more complex configuration:  that also checks which directory the .js file is in before setting the cache heading.
40 1 dj jones
41 1 dj jones
Etienne suggested this nginx configuration  (see Issues #13564):
42 1 dj jones
43 1 dj jones
<pre>
44 1 dj jones
location ~* ^(?:(?:plugin_assets/|themes/).+/)(?:javascripts|stylesheets|images)/.+\.(?:css|js|jpe?g|gif|htc|ico|png|html)$ {
45 1 dj jones
</pre>
46 1 dj jones
47 1 dj jones
The simple case, that will break Redmine, does not care about which directory eg:
48 1 dj jones
<pre>
49 1 dj jones
location ~* \.(ico|css|js|gif|jp?g|png)(\?[0-9]+)?$ {
50 1 dj jones
expires 365d;
51 1 dj jones
}
52 1 dj jones
</pre>