Today I’d like to continue browser’s cache topic and discuss one of the ways user can invalidate cached resources. I’m talking about F5 versus CTRL+F5 shortcuts (versus other ways to “refresh” the page) in modern browsers. So what is the difference between pressing F5 or CTRL+F5 in a browser window?
HTTP Request Types
First, let’s step back for a moment and take a look into HTTP theory.
Web browsers make two types of requests over HTTP(S) – conditional requests and unconditional requests.
An unconditional request is made when the client browser does not have a cached copy of the resource available locally. In this case, the server is expected to return the resource with a HTTP/200 OK response. If the response’s headers allows it, the client may cache this response in order to reuse it later.
If the browser later needs to retrieve the resource which is available locally (in cache). That resource’s header are checked in order to determine whether it is fresh or not. If the cached copy is still fresh then no server request will be made at all.
After that if the browser needs the resource, which is in the cache, but expired already (older than its max-age or past the Expires date), then client will make conditional request in order to figure out whether cached copy could be reused or should be replaced with some fresh version of the resource. The conditional request contains an If-Modified-Since and/or If-None-Match header that indicates to the server what version of the content the browser already has in its cache. If browser’s version is still valid, the server will return HTTP/304 Not Modified headers with no body, otherwise it can return HTTP/200 OK response with the new version of the resource.
Test user-invoked refresh
So, in theory F5 should lead to no request (if resource is in the cache and is fresh) or conditional request (in case when resource is in the cache, but not fresh anymore). CTRL+F5 on the other hand should lead to unconditional request, bypassing the cache altogether. Another thing I noted is that Cache-Control: no-cache and Pragma: no cache headers were added to requests after pressing CTRL+F5 in Chrome.
Curiosity is a scary thing, so I decided to develop small test page and investigate browser’s behavior (and cache behavior) while refreshing the page in different ways.
My test page contains three .js resources, one of them has Cache-Control: no-cache in its response header. Another one has Cache-Control: private, max-age=15. And the last one has no cache preferences. So here are my findings:
Link navigation – means clicking on Navigate away from the page link and then on Return Back link. This is not a true refresh method, but some users expect to see fresh content each time they visit a page (no matter how they get there).
Another interesting fact is that if switch IE to HTTP 1.0 then the browser’s won’t use Cache-Control, but will send Pragma: no-cache instead.
In order to deliver the best usability for your website, you should be aware of how exactly users deliver the message “I want fresh content now” to the browser. Otherwise your cache policy could be sticking point on the way to deliver fresh content to the user.
In some cases its better to add “Refresh” button on the page, so it will do the job in the way your app expect it.
Source code available on GitHub.