做后台管理系统的小伙伴应该都遇到过:后端部署了新版本,打开浏览器发现界面怎么还是旧的?因为 SPA 不刷新,用户压根不知道。下面聊聊这个问题的痛点和几种处理方案。
问题出在哪
现代前端系统普遍采用 SPA 架构,路由切换无刷新,体验好了,但部署更新后麻烦就来了。用户长时间停留在系统里,不会触发页面整体刷新,浏览器一直用的是首次加载的旧资源,完全感知不到已经发布了新版。
另一个坑是 hash 资源覆盖部署:打包时每个文件带哈希,上线时旧文件被同名但哈希不同的新文件替换,用户缓存的旧请求就指向了不存在的资源,出现白屏、菜单卡死、接口报错。这类问题在后台管理系统、企业办公平台里尤其突出,用户不会主动关页面,旧版前端配上新版接口,数据提交都可能出错。
不主动通知刷新,直接导致功能不一致、页面异常、业务报错,甚至影响数据准确性,还徒增排查成本。
准备一个版本指纹
无论用哪种方案,都需要一个能被前端拉到的版本文件。在 public 下放个 manifest.json:
{
"version": 1774319356413,
"appVersion": "3.8.5",
"buildEnv": "production",
"buildHash": "19d1dacc9fd",
"needRefresh": false,
"msg": "更新内容如下:\n--1.更新提示机制"
}
每次构建自动写入时间戳,可以用 webpack 插件:
// vue.config.js
const fs = require('fs');
const path = require('path');
const buildManifestContent = {
appVersion: require('./package.json').version,
version: ().(),
: process..,
: ().().(),
: ,
:
};
. = {
: {
: [
{
() {
= () => {
manifestPath = path.(__dirname, );
{
originalContent = {};
(fs.(manifestPath)) {
fileStr = fs.(manifestPath, );
originalContent = .(fileStr);
}
finalContent = { ...originalContent, ...buildManifestContent };
fs.(manifestPath, .(finalContent, , ), );
.();
} (error) {
.(, error);
}
};
compiler...(, writeManifest);
compiler...(, writeManifest);
}
}
]
}
};

