实现原理
- 生成版本信息 JSON 文件
- 使用 Node.js 脚本获取
package.json
中的版本信息,并保存为versionInfo.json
文件,存放在构建打包目录下(如public
目录)。
- 使用 Node.js 脚本获取
- 监听页面显示和隐藏
- 监听
visibilitychange
事件。当页面显示时,请求dist
根目录下的versionInfo.json
文件,对比当前版本与历史版本是否一致。如果不一致,则刷新浏览器。
- 监听
- 环境变量配置
- Vite 打包项目使用
.env
文件与import.meta.env
保存当前打包变量。Webpack 项目则使用definePlugin
插件与process.env
。
- Vite 打包项目使用
Node.js 脚本实现
import { execSync } from 'child_process'; // 子进程 execSync 执行命令
import fs from 'fs';
import dotenv from 'dotenv'; // 加载 .env 文件中的环境变量
import dayjs from 'dayjs';
const versionInfoPath = 'versionInfo.json'; // 版本信息路径
const pagePath = 'package.json';
const publicPath = 'public'; // 存放于 public 目录
const autoPush = false; // 是否自动提交 Git
const isVite = true; // 是否使用 Vite 构建
let pageInfo = {};
let versionInfoObj = {}; // 存储版本信息
// 读取现有版本信息
if (fs.existsSync(versionInfoPath)) {
versionInfoObj = JSON.parse(fs.readFileSync(versionInfoPath).toString());
}
// 读取 package.json 中的版本号
if (fs.existsSync(pagePath)) {
pageInfo = JSON.parse(fs.readFileSync(pagePath).toString());
}
// 判断版本是否已存在
if (pageInfo && versionInfoObj.version === pageInfo.version) {
console.warn('警告: 当前版本信息已存在!\n');
} else {
versionInfoObj = {
version: pageInfo.version,
name: pageInfo.name,
date: dayjs().format('YYYY-MM-DD HH:mm:ss'),
};
fs.writeFileSync(versionInfoPath, JSON.stringify(versionInfoObj, null, 2));
console.log(`执行成功: 文件地址为 ${process.cwd()}/${versionInfoPath}\n`);
}
// 将 versionInfo 文件移至 public 目录
if (fs.existsSync(publicPath)) {
fs.writeFileSync(`${process.cwd()}/${publicPath}/${versionInfoPath}`, fs.readFileSync(versionInfoPath));
}
// 更新 .env 文件中的 VITE_GIT_INFO 变量
if (isVite) {
const envPath = `${process.cwd()}/.env`;
const envContent = fs.readFileSync(envPath, { encoding: 'utf-8' });
const envVariables = dotenv.parse(envContent);
envVariables.VITE_GIT_INFO = JSON.stringify(versionInfoObj);
const updatedEnvContent = Object.entries(envVariables)
.map(([key, value]) => `${key}=${value}`)
.join('\n');
fs.writeFileSync(envPath, updatedEnvContent, { encoding: 'utf-8' });
console.log('.env 文件已更新');
}
配置脚本命令
在 package.json
中添加以下脚本:
"scripts": {
"build:git": "npm run get-git && vite build",
"get-git": "node scripts/useNodeGetGitInfo.js"
}
监听 visibilitychange
事件
在项目入口 JS 文件中,添加以下代码以自动刷新页面:
const gitInfo = import.meta.env.VITE_GIT_INFO;
const gitInfoObj = gitInfo && JSON.parse(gitInfo);
if (document.visibilityState === 'hidden') return;
fetch(`/versionInfo.json?v=${Date.now()}`)
.then(res => res.json())
.then(data => {
if (data.version !== gitInfoObj.version) {
location.reload();
}
});