Cache busting intermittently failing - would this work?

Hey!

I’m running liveview in production and it’s great. I’m deploying using docker / releases and mix phx.digest.

Everything works perfectly 99% of the time.

However sometimes the css and js files are not loading properly. Someone will access the site one day, I’ll deploy, then the next day it looks like the stylesheet isn’t loading at all or certain buttons can’t be clicked.

Of course when the user clears their cache it works again… but they often don’t know how.

Phoenix has this on static changed solution… but window.reload doesn’t seem to remove memory cache of static assets so I wrote this:

<%= if @static_changed? do %>
  <div id="reload-static" style="width: 100%; height: 80vh; display: flex; justify-content: center; align-items: center;">
    <p>The app has been updated. <a href="#" onclick="window.location.reload(true)" style="text-decoration:underline;">Click here to reload</a>.</p>
  </div>
  <script>
    const js = document.getElementById('main-js')
    const css = document.getElementById('main-css')
    fetch(js.src, {cache: "reload"})
    fetch(css.href, {cache: "reload"})
  </script>
<% end %>

I do inline styles because the stylesheet styles are not there.

Then I’m refetching the css and js static assets and then asking the user to click reload.

Do you think this is an effective solution?

I’m also half wondering if I’m messing something up with docker builds and static assets but I’m not sure.

Thanks!

Hi! I think there are multiple things going on here.

  • When users see the page apparently without styles, that would imply the markup itself is cached on the client and references a stylesheet, that no longer exists in the new release (the digest hash changed in the filename because the content changed for example). This problem would be exacerbated if there’s only a short or no cache policy applied the static assets (meaning the client will try to refetch the old assets). There are a couple mitigations that come to mind:
    • Disallow caching for the document or set it two a reasonable default (in the http headers).
    • More forgiving caching policy for the static assets
    • Upload the static assets to a storage bucket/CDN prior to deployment (and keep the old assets around). This has the added benefit that rolling updates just work without having to resort to session affinity and hoping for best.
  • Your solution, as far as I understand, deals with clients that are already connected and reconnect to the new release when the old one is replaced. Reloading the assets the client currently references in their DOM will be refreshing the old assets. Reloading the page should normally do the trick (because digest hashes should automatically bust the cache), but if it doesn’t see above :slight_smile:

Thank you! I’ll try a couple solutions you mentioned there. Appreciate it!