Using Next.js as a single-page app (SPA) comes with many benefits but has a major downside: stale sessions. Because users never need to refresh the page, they can go days or weeks without doing so. This makes evolving your API much more difficult. Fully deprecating an endpoint can take weeks or even months.
A common pattern to solve this problem is prompting users to refresh:
To our surprise, there wasn’t a drop-in way to do this in Next.js. They offer some mechanisms to trigger a refresh upon page navigation, but this can be jarring for users without warning. To fill this gap, we’re sharing how we solved this problem.
In short, have the Next.js front-end track its version number and poll the Next.js server for what the latest version number is. When they differ, prompt the user to refresh.
// pages/api/requires-refresh/[version].ts
export const LATEST_APP_VERSION = 105;
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<boolean>
) {
const requestVersion = parseInt(req.query.version);
const needsRefresh = requestVersion < LATEST_APP_VERSION;
res.status(200).json(needsRefresh);
}
import { LATEST_APP_VERSION as versionOnLoad } from "./api/requires-refresh/[version]";
const RefreshChecker = () => {
const [showRefreshPrompt, setShowRefreshPrompt] = React.useState(false);
React.useEffect(() => {
async function checkRefresh() {
const url = "/api/requires-refresh/" + versionOnLoad;
const res = await fetch(url);
if (res.ok) {
const needsRefresh = await res.json();
if (needsRefresh) {
setShowRefreshPrompt(true);
}
}
}
const id = setInterval(checkRefresh, 60_000);
return () => clearInterval(id);
}, []);
if (showRefreshPrompt) {
// Render your refresh prompt here
return <div>Refresh required</div>;
} else {
return null;
}
};
This approach works great for allowing engineers to prompt user refreshes when needed by changing a single line of code. It’s simple and works out of the box with Next.js. By sharing our approach, we hope to help other teams who face similar challenges.
At Comulate, we’re building a product-obsessed engineering team. If this and similar challenges sound interesting, we’d love to chat! See our open roles here.