新版本发布后,怎样提示正在使用旧页面的用户刷新?

先理解原理和示例,再练习完整口述与追问。

构建时生成版本号写入 version.json 与页面;前端在页面重新可见、路由切换或定时轮询时请求 version.json?t=时间戳(或配置 no-cache),版本不同则提示刷新。动态导入 chunk 失败时,捕获错误后提示或自动刷新一次。使用 Service Worker 的项目在新 worker 进入 waiting 时提示。

单页应用打开后不会重新请求 index.html,新版本发布后,用户仍在执行旧代码,旧代码中的懒加载路由引用旧的 chunk 文件名;如果服务器已删除旧文件,切换路由就会失败(Webpack 报 ChunkLoadError,Vite 触发 vite:preloadError 事件)。所以除了提示,还要保留旧版本资源一段时间。

检测时机:visibilitychange 回到前台时检查一次,比固定高频轮询更节省;也可以由服务端在接口响应头中带版本号,或通过 WebSocket 推送。提示应该由用户选择刷新时机,避免打断正在填写的表单;对于强制升级(接口不兼容)才自动刷新。

js
const current = import.meta.env.VITE_APP_VERSION
async function checkVersion() {
  const response = await fetch(`/version.json?t=${Date.now()}`, { cache: 'no-store' })
  if (!response.ok) return
  const { version } = await response.json()
  if (version !== current) showUpdateBanner()
}
document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') checkVersion() })
window.addEventListener('vite:preloadError', event => {
  event.preventDefault()
  if (!sessionStorage.getItem('reloaded-for-chunk')) {
    sessionStorage.setItem('reloaded-for-chunk', '1')
    location.reload()
  }
})

自动刷新时没有防循环标记,资源确实缺失会导致无限刷新;version.json 被 CDN 缓存会让检测失效。

我会在构建时生成版本号,写进页面和 version.json。前端在页面回到前台或路由切换时,用不缓存的方式请求 version.json 比较,不同就弹出提示,让用户选择刷新,避免打断操作。同时监听懒加载 chunk 失败,比如 Vite 的 preloadError,刷新一次并用 sessionStorage 防止循环。服务端也要保留上一个版本的资源,PWA 项目则在新 Service Worker waiting 时提示。