发布新版本,通知浏览器刷新

335 阅读2分钟

背景:

当我们重新部署前端项目时,用户一直停留在页面,未刷新使用,会存在功能使用差异问题,若后端接口不检验,兼容,会产生脏数据。 每次上线都要人工传播。

因此当前端部署项目后,需要提醒用户有去重新加载页面。

需求:

版本更新后,系统自动出现刷新提醒。

立即刷新:刷新浏览器。 不再提醒,直到下次发版再提醒。

稍后刷新:一小时后再次出现提示弹窗。

image.png

前提:确保浏览器不缓存,刷新可获取最新版本。

  1. 在 .html 页面加 meta 标签, 确保浏览器每次都能获取到页面的最新版本。
// 浏览器不要使用缓存。 
<meta http-equiv="pragma" content="no-cache"> 
// 不适用缓存、不存储、页面过期重新请求 
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate"> 
// 立即过期 
<meta http-equiv="expires" content="0">

  1. 脚手架配置, 打包后 css 和 js 的名字后面都哈希值或者时间戳。
output: { 
    //静态资源分类打包 
    chunkFileNames: 'static/js/[name]-[hash].js', 
    entryFileNames: 'static/js/[name]-[hash].js', 
    assetFileNames: 'static/[ext]/[name]-[hash].[ext]', 
}

3. 后端 nginx 配置,让 index.html 不缓存。

location = /index.html { add_header Cache-Control "no-cache, no-store"; }

有新版本发布,弹窗提醒。

原理: 对比本地html的版本和远程的版本号是否一致。

创建auto-update.js, 定时刷新,提醒弹窗。

  • 定时任务每隔1小时,检查是否有新版本。 对比本地version和远程version
import { MessageBox } from 'element-ui'
localStorage.setItem('needTip', 'true'); // 是否开启刷新提示

function checkVersion () {
  return new Promise(resolve => {
    fetch(`${window.location.origin}/admin/version.json?v=${new Date().getTime()}`, {
      headers: {
        'Cache-Control': 'no-cache'
      }
    }).then(async res => {
      try {
        const text = await res.text();
        const data = JSON.parse(text);
        resolve(data.version === Number(document.querySelector('#appVersion').content));
      } catch (error) {
        console.error('Error fetching or parsing version.json:', error);
        resolve(false); // Resolve with false indicating version check failed
      }
    }).catch(error => {
      console.error('Fetch error:', error);
      resolve(false); // Resolve with false indicating version check failed
    });
  });
}


// 是否弹出提示窗,防止重复弹出
let isShow = false
function autoRefresh () {
  if (localStorage.getItem('needTip') == 'true') {
    setTimeout(async () => {
      if (!isShow) { //  防止重复弹出
        const flag = await checkVersion();
        if (!flag) {
          isShow = true
          MessageBox.confirm('检测到当前版本不是最新版本,刷新浏览器后即可正常使用。', '提示', {
            confirmButtonText: '立即刷新',
            cancelButtonText: '稍后刷新',
            type: 'warning',
          }).then(() => {
            window.location.reload();
          }).catch(() => {
            isShow = false // 重置是否弹出提示窗
          });
        }
      }
      autoRefresh();
    }, 3600000)
  }
}
// 一小时执行一次
autoRefresh();

main.js 中引入。

// 引入自动更新提醒 
import "@/utils/auto-update.js"

创建version数据,并打包传到远程。

// version.js
const fs = require('fs');
const timestamp = new Date().getTime();
fs.writeFile('./public/version.json', `{"version": ${timestamp}}`, err => {
  if (err) {
    console.error(err);
  }
});


打包命令配置: 执行打包命令,创建version。
"build:rel": "node version.js && vue-cli-service build  --mode release",

html添加version。

html 添加标签
<meta id="appVersion" name="version" content="<%= htmlWebpackPlugin.options.version%>" />


vite.config.js文件中配置
const AppVersion = require('./public/version.json')
//  可以在 index.html 文件内访问到版本号(AppVersion.version)
config.plugin('html').tap(args => {
  args[0].version = AppVersion.version;
  return args;
});

image.png