Skip to content

项目版本更新提示用户刷新

TIP

在开发过程中,我们经常会遇到项目版本更新,需要用户刷新页面才能看到最新的效果。

方法有很多种:各有利弊

  1. 使用websocket/sse实现版本检查
  2. 使用webpack-dev-server实现版本检查
  3. 使用npm-watch实现版本检查
  4. 请求接口时传递版本号,后端返回最新版本号,前端判断是否需要刷新
  5. 使用service worker实现版本检查
  6. 使用npm-version-check实现版本检查
  7. 使用打包文件hash实现版本检查
  8. 使用轮询实现版本检查

我觉得比较好的方法

请求封装自定义请求头,传递版本号,后端返回最新版本号,前端判断是否需要刷新。对服务器压力小,对用户影响小。

WARNING

反正都要请求接口的,带一个版本号怎么了?后端判断一下,返回最新版本号,前端判断一下,需要刷新就刷新,不需要刷新就继续用。轮询?你服务器很牛逼吗,隔一下检测一下版本?吃饱了撑得吗?

javascript
import axios from 'axios';

// 当前前端版本号(可以从package.json或其他配置中获取)
const APP_VERSION = '1.0.0';

// 请求拦截器
axios.interceptors.request.use(config => {
  // 在请求头中添加版本号
  config.headers['X-App-Version'] = APP_VERSION;
  return config;
}, error => {
  return Promise.reject(error);
});

// 响应拦截器
axios.interceptors.response.use(response => {
  return response;
}, error => {
  if (error.response && error.response.status === 426) {
    // 版本不匹配,提示用户刷新,这个弹窗可以用其他方式实现,如弹窗、Toast、通知等等
    alert('检测到新版本,请刷新页面以获取最新功能!');
  }
  return Promise.reject(error);
});
import axios from 'axios';

// 当前前端版本号(可以从package.json或其他配置中获取)
const APP_VERSION = '1.0.0';

// 请求拦截器
axios.interceptors.request.use(config => {
  // 在请求头中添加版本号
  config.headers['X-App-Version'] = APP_VERSION;
  return config;
}, error => {
  return Promise.reject(error);
});

// 响应拦截器
axios.interceptors.response.use(response => {
  return response;
}, error => {
  if (error.response && error.response.status === 426) {
    // 版本不匹配,提示用户刷新,这个弹窗可以用其他方式实现,如弹窗、Toast、通知等等
    alert('检测到新版本,请刷新页面以获取最新功能!');
  }
  return Promise.reject(error);
});

后端定义一个中间件或者函数都可以,根据业务需求来定。

javascript
const express = require('express');
const app = express();
const CURRENT_VERSION = '1.0.1'; // 后端当前版本

app.use((req, res, next) => {
  const clientVersion = req.headers['x-app-version'];
  
  if (clientVersion !== CURRENT_VERSION) {
    return res.status(426).json({
      code: 426,
      message: 'Version mismatch',
      currentVersion: CURRENT_VERSION
    });
  }
  
  next();
});

// 其他路由...
const express = require('express');
const app = express();
const CURRENT_VERSION = '1.0.1'; // 后端当前版本

app.use((req, res, next) => {
  const clientVersion = req.headers['x-app-version'];
  
  if (clientVersion !== CURRENT_VERSION) {
    return res.status(426).json({
      code: 426,
      message: 'Version mismatch',
      currentVersion: CURRENT_VERSION
    });
  }
  
  next();
});

// 其他路由...

使用vite-plugin-version在构建时生成版本信息

安装插件

bash
npm install vite-plugin-version --save-dev
npm install vite-plugin-version --save-dev

配置 vite.config.js 生成版本信息

js
import { defineConfig } from 'vite';
import ViteVersion from 'vite-plugin-version';

export default defineConfig({
  plugins: [
    ViteVersion({
      output: 'src/assets/version.json', // 指定版本文件输出路径
    }),
  ],
});
import { defineConfig } from 'vite';
import ViteVersion from 'vite-plugin-version';

export default defineConfig({
  plugins: [
    ViteVersion({
      output: 'src/assets/version.json', // 指定版本文件输出路径
    }),
  ],
});

构建时会在 src/assets/version.json 生成一个类似如下的文件

json
{
  "version": "1.0.0",
  "buildTime": "2025-06-14T17:00:00Z"
}
{
  "version": "1.0.0",
  "buildTime": "2025-06-14T17:00:00Z"
}

前端定时请求版本信息

在 Vue 组件中,设置一个定时任务来轮询请求版本信息文件,并与当前版本进行对比。如果版本不一致,提示用户更新。

获取当前版本并与版本文件对比

在 main.js 或 Vue 组件中,实现版本检测功能。

js
import { ref, onMounted } from 'vue';

const currentVersion = import.meta.env.VITE_APP_VERSION || '1.0.0'; // 读取当前版本号,或者从环境变量中获取

const checkForUpdates = async () => {
  try {
    const response = await fetch('/src/assets/version.json'); // 请求版本信息文件
    const data = await response.json();
    if (data.version !== currentVersion) {
      showUpdatePrompt();
    }
  } catch (error) {
    console.error('检查更新失败:', error);
  }
};

const showUpdatePrompt = () => {
  const confirmUpdate = confirm('发现新版本,是否立即更新?');
  if (confirmUpdate) {
    window.location.reload(); // 刷新页面加载新版本
  }
};

onMounted(() => {
  setInterval(checkForUpdates, 60000); // 每60秒检查一次版本
  checkForUpdates(); // 初始检查一次
});
import { ref, onMounted } from 'vue';

const currentVersion = import.meta.env.VITE_APP_VERSION || '1.0.0'; // 读取当前版本号,或者从环境变量中获取

const checkForUpdates = async () => {
  try {
    const response = await fetch('/src/assets/version.json'); // 请求版本信息文件
    const data = await response.json();
    if (data.version !== currentVersion) {
      showUpdatePrompt();
    }
  } catch (error) {
    console.error('检查更新失败:', error);
  }
};

const showUpdatePrompt = () => {
  const confirmUpdate = confirm('发现新版本,是否立即更新?');
  if (confirmUpdate) {
    window.location.reload(); // 刷新页面加载新版本
  }
};

onMounted(() => {
  setInterval(checkForUpdates, 60000); // 每60秒检查一次版本
  checkForUpdates(); // 初始检查一次
});

这是其中一种实现方法

javascript
// main.js

// 检查版本号
function checkVersion() {
  return fetch('/api/version')
    .then(response => response.json())
    .then(data => {
      const latestVersion = data.version
      const currentVersion = '1.0.0' // 当前版本号
      return { isLatest: latestVersion === currentVersion, latestVersion }
    })
    .catch(error => {
      console.error('版本检查失败:', error)
      return { isLatest: true, latestVersion: null } // 默认视为最新版本
    })
}

// 显示更新提示(非阻塞)
function showUpdatePrompt(latestVersion) {
  const shouldUpdate = confirm(`检测到新版本 ${latestVersion},是否刷新以更新?`)
  if (shouldUpdate) {
    window.location.reload()
  }
}

// 初始化检查
checkVersion().then(({ isLatest, latestVersion }) => {
  if (!isLatest && latestVersion) {
    // 提示用户更新,但不强制刷新
    showUpdatePrompt(latestVersion)
  }
})
// main.js

// 检查版本号
function checkVersion() {
  return fetch('/api/version')
    .then(response => response.json())
    .then(data => {
      const latestVersion = data.version
      const currentVersion = '1.0.0' // 当前版本号
      return { isLatest: latestVersion === currentVersion, latestVersion }
    })
    .catch(error => {
      console.error('版本检查失败:', error)
      return { isLatest: true, latestVersion: null } // 默认视为最新版本
    })
}

// 显示更新提示(非阻塞)
function showUpdatePrompt(latestVersion) {
  const shouldUpdate = confirm(`检测到新版本 ${latestVersion},是否刷新以更新?`)
  if (shouldUpdate) {
    window.location.reload()
  }
}

// 初始化检查
checkVersion().then(({ isLatest, latestVersion }) => {
  if (!isLatest && latestVersion) {
    // 提示用户更新,但不强制刷新
    showUpdatePrompt(latestVersion)
  }
})

程序员小洛文档