JavaScript Caching – Dealing with Browser Cache in Single-Page Apps

cachingjavascriptweb-applications

I'm trying to figure out how to properly handle the web browser cache for single page apps.

I have a fairly typical design: several HTML, JS and CSS files implementing the SPA, and a bunch of JSON data that's consumed by the SPA. Problems arise when I want to push an update: I update the static portion of the site and the code that generates the JSON at the same time, but client browsers often have the static portion cached, so old code tries to process the new data and may (depending on changes made) run into problems. (In particular, IE seems more aggressive than Chrome or Firefox about using cached JS without revalidating.)

What's the best way to handle this?

  1. Make sure my JSON changes are backwards-compatible, and assume browser caches will expire in a reasonable timeframe.
  2. Embed some sort of version number in both the static JS and the JSON, then execute window.location.reload(true); if they don't match.
  3. Figure out the appropriate combination of headers (must-revalidate or no-cache or whatever; sources vary on how to do this) to ensure that browsers always revalidate all resources on every load, even if it means a few extra round trips to load the site.
  4. Micro-manage my cache-control and expires headers so that static content expires when I want to push an update.
  5. Something else?

Best Answer

You need a cache busting solution. The role of cache busting is:

  1. Rename resources to a unique name depending on their content.
  2. Update all references to those resources.

In a Grunt-based project it's common to use grunt-rev to ensure that all files that need to be refreshed are given unique names, based on their content.

If you ensure that your JSON files get cachebusting filenames along with the references to them in your Javascript, clients will always load the JSON files that the Javascript expects.

The advantage of hash-based file naming is that files that have not changed will get the same filenames after cache-busting, so browsers can continue to safely use cached content when it has not changed.

Obviously this is the kind of thing you want to be automated as part of your project's production build so you don't have to keep track of changing file names & references manually.

Related Topic