How to force update Single Page Application (SPA) pages?
Similar to Steve Taylor's answer but instead of versioning API endpoints I would version the client app, in the following way.
With each HTTP request send a custom header, such as:
X-Client-Version: 1.0.0
The server would then be able to intercept such header and respond accordingly.
If the server is aware that the client's version is stale, for example if the current version is 1.1.0
, respond with an HTTP status code that will be appropriately handled by the client, such as:
418 - I'm a Teapot
The client can then be programmed to react to such a response by refreshing the app with:
window.location.reload(true)
The underlying premise is that the server is aware of the latest client version.
EDIT:
A similar answer is given here.
You can have a React component make an ajax request to your server, when the application loads, to fetch "interface version". In the server API, you can maintain an incremental value for the client version. The React component can store this value on the client (cookie/local storage/etc). When it detects a change, it can invoke window.location.reload(true);
which should force the browser to discard client cache and reload the SPA. Or better still, inform the end-user that a new version will be loaded and ask them if they wish to save the work and then reload etc. Depends on what you wanna do.
You can send app’s version with every response from any endpoint of your API. So that when the app makes any API request you can easily check there’s a new version and you need a hard reload. If the version in the API response is newer than the one stored in localStorage, set window.updateRequired = true
. And you can have the following react component that wraps react-router
's Link
:
import React from 'react';
import { Link, browserHistory } from 'react-router';
const CustomLink = ({ to, onClick, ...otherProps }) => (
<Link
to={to}
onClick={e => {
e.preventDefault();
if (window.updateRequired) return (window.location = to);
return browserHistory.push(to);
}}
{...otherProps}
/>
);
export default CustomLink;
And use it instead of react-router's Link
throughout the app. So whenever there's an update and the user navigates to another page, there will be a hard reload and the user will get the latest version of the app.
Also you can show a popup saying: "There's an update, click [here] to enable it." if you have only one page or your users navigate very rarely. Or just reload the app without asking. It depends on you app and users.