Problem: When you deploy a new version of your SPA, users with a tab open...
Problem: When you deploy a new version of your SPA, users with a tab open will keep using the old SPA code.
Yesterday, I shared one solution. People suggested dozens of useful variations and alternatives. 🙏
So, here are the best options in the massive thread.
6 ways to tell the SPA a new release is available, simplest options first:
1. Write the version from package.json into index.html as part of the build process. Poll index.html every x minutes and compare the server's index.html to the client's index.html.
2. Create an endpoint on the UI web server that reads the package.json version, and returns it. Poll this every x minutes. This is more efficient than option 1, because the payload is smaller.
3. Use web sockets or server sent events to push a notification to the UI after a deploy instead. This is especially attractive if you’re already using these technologies.
4. Use a service worker to notify the user when the UI is stale. For example, Vite's PWA plugin supports this.
5. Use an API proxy like Cloudfront to fetch the version without involving the backend. More here: https://www.rehanvdm.com/blog/using-a-cloudfront-api-proxy-to-invalidate-a-single-page-application-without-polling
6. Specify the app version in each HTTP call from the UI via a x-app-version header (or whatever name you like). Validate the x-app-version header on the API server. If x-app-version doesn't match the server's version, notify the UI in the response, either via an HTTP 205, 400, or 422 (the HTTP response you return depends on whether you want calls from a “stale” UI to succeed).
Once the UI is aware a newer version exists, you need to decide when and how to notify the user.
Here are 3 ways:
1. Don’t. Just automatically refresh. Not generally recommended, but certainly simple. (You could even use a simple meta refresh to do this, or a little JS code that forces a refresh off-hours. But this risks people losing work in progress, so I don't recommend it).
2. Don’t. Instead, when a new version is detected, disable client-side routing and do server routing temporarily. This way, when the user clicks on a link, the app does a full reload. This avoids the user losing work, and doesn't interrupt the user's workflow. Quite slick.
3. Display a dialog that says “Update available. Click here to reload.” Optionally, let the user click cancel if you want to allow them to refresh later. The advantage here is the user gets a "heads up" when the UI changes.