So there's two important distinctions with caching that people often confuse:
You seem to want to use some validation technique (modified time or ETag) give give you good caching but with instant reloading when you do change something but that is not the best way as you basically can only use the second part of above when it's the first that gives you the benefit. Great article here on why latency is the issue btw: http://www.nateberkopec.com/2015/11/05/page-weight-doesnt-matter.html. Lots of other good info in that article so do recommend reading it all. So, you ultimately want really long Cache-Controls, so after the first download it stays in the cache. But then you want to force users to reload as quickly as possible when you change things. And those are opposing requirements. So your options are to either use cache-busting techniques, or to basically ignore the issue. Cache-busting techniques basically fool the browser into thinking it's asking for a different resource. For example adding parameters to URL. CSS tricks has a great page on various techniques here: https://css-tricks.com/strategies-for-cache-busting-css/. Based on your deployment technique that won't work based on mtime so you really need to add a version number here instead but how easy that is depends on how you create pages and the build process you use. The other option is to ignore the issue until the resources have expired. This might seem odd, but is increasingly my preferred option so let me explain why. What I do is set up a very short expiry time for key resources that are liable to change (e.g. HTML, CSS and JS). Say an hour or 3. Then accept that people will get the cached, potentially stale resource, for that time. Most recommendations are for a long expiry time in a hope to cache your page for a while but given that caches aren't as big as some people think (again see the article referenced above) that benefit is mostly not seen IMHO except for very frequent visitors. So you've the hassle of long expiry with none of the benefits. Using short expiries has several benefits:
The downsides are:
And ETags are pretty useless in my view due to their poor implementation. Apache uses a combination of file size and modified time by default - which as you rightly point out may not identify whether files contents have changed. Inode is basically the file reference on disk so similar. And is also not recommended when using a load balancer and multiple web servers, as inode will be different in each (which is why it's not used by default anymore). A hash of contents would be better (though potentially slower). But main issue with Etags on Apache is that they don't work when you gzip your data (which you should do)! See my blog post here about this: https://www.tunetheweb.com/performance/http-performance-headers/etag/. You should not use Etags on Apache for this reason. And also they are fairly useless for small resources (like text ones that you will wish to zip) as discussed above. Last modified is almost as good and doesn't have the bug with gzipped resources. Having proper caching is one of the biggest performance improvements you can make to your site. Without it a site can feel slow and laggy as you browse around it - no matter how fast your server or the visitors computer. With it, a site can feel zippy and responsive even with a slow server. However it does complicate things as you've noticed so requires a good bit of thought as to how to set it up properly. I go into a bit more detail on how to configure Apache for it here: https://www.tunetheweb.com/performance/http-performance-headers/caching/ Hope that helps - even if it is a bit long winded and unfortunately doesn't give you the quick fix you were no doubt looking for! |