Handling Page Refresh and Cache Updates in Vue SPA with Vite
This article explains why users may still see outdated pages after a Vue SPA deployment, analyzes the caching issues caused by static asset headers, and provides both back‑end coordinated and pure front‑end solutions—including WebSocket, SSE, ETag polling, custom Vite plugins, and example code—to automatically detect and prompt updates.
Introduction
Boss: The new feature is live, but users still see the old page. Developer: Ask them to refresh or clear cache. Boss: That’s a poor user experience; we need a better way.
Product Introduction
For consumer‑facing (C‑end) applications, textual content often needs updates; old wording can cause public opinion issues, so the page must be refreshed after updates so users see the latest version.
Why the Issue Occurs
The project is a Vue SPA served through Nginx with static resources cached via Cache-Control headers. After a normal front‑end redeployment, users who re‑visit the site receive the newest page.
However, most users stay on the current page; after a front‑end deployment they continue to see the old version until they manually refresh.
Problems Caused
If the back‑end API changes, the old front‑end may cause API errors.
Users may not see the new UI, leading to a bad experience.
Online bugs fixed in the new version remain visible to users still on the old page.
Solution
Front‑end and back‑end cooperation:
WebSocket
SSE (Server‑Sent Events)
Pure front‑end approach (examples use Vite + Vue 3):
Polling HTML ETag / Last‑Modified
In App.vue add the following code:
const oldHtmlEtag = ref();
const timer = ref();
const getHtmlEtag = async () => {
const { protocol, host } = window.location;
const res = await fetch(`${protocol}//${host}`, {
headers: {
"Cache-Control": "no-cache",
},
});
return res.headers.get("Etag");
};
oldHtmlEtag.value = await getHtmlEtag();
clearInterval(timer.value);
timer.value = setInterval(async () => {
const newHtmlEtag = await getHtmlEtag();
console.log("---new---", newHtmlEtag);
if (newHtmlEtag !== oldHtmlEtag.value) {
Modal.destroyAll();
Modal.confirm({
title: "Detected new version, update?",
content: "New version content:",
okText: "Update",
cancelText: "Cancel",
onOk: () => {
window.location.reload();
},
});
}
}, 30000);Additional file versionData.json is generated by a custom Vite plugin.
Create a custom plugin at /plugins/vitePluginCheckVersion.ts :
import path from "path";
import fs from "fs";
export function checkVersion(version: string) {
return {
name: "vite-plugin-check-version",
buildStart() {
const now = new Date().getTime();
const version = {
version: now,
};
const versionPath = path.join(__dirname, "../public/versionData.json");
fs.writeFileSync(versionPath, JSON.stringify(version), "utf8", (err) => {
if (err) {
console.log("Write failed");
} else {
console.log("Write succeeded");
}
});
},
};
}Import the plugin in vite.config.ts :
import { checkVersion } from "./plugins/vitePluginCheckVersion";
plugins: [
vue(),
checkVersion(),
]Add update‑checking logic in App.vue :
const timer = ref();
const checkUpdate = async () => {
let res = await fetch('/versionData.json', {
headers: {
'Cache-Control': 'no-cache',
},
}).then((r) => r.json());
if (!localStorage.getItem('demo_version')) {
localStorage.setItem('demo_version', res.version);
} else {
if (res.version !== localStorage.getItem('demo_version')) {
localStorage.setItem('demo_version', res.version);
Modal.confirm({
title: 'Detected new version, update?',
content: 'New version content: ' + res.content,
okText: 'Update',
cancelText: 'Cancel',
onOk: () => {
window.location.reload();
},
});
}
}
};
onMounted(() => {
clearInterval(timer.value);
timer.value = setInterval(async () => {
checkUpdate();
}, 30000);
});Alternatively, use the community plugin plugin-web-update-notification :
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { webUpdateNotice } from '@plugin-web-update-notification/vite';
export default defineConfig({
plugins: [
vue(),
webUpdateNotice({
logVersion: true,
}),
]
});These approaches enable automatic detection of new deployments and prompt users to refresh, eliminating stale pages without manual instructions.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.