方案来源于团队分享后的总结实现,文中代码并未在实际产品中是使用,仅供参考。
背景
由于在spa模式的应用中页面的内容变化不再引起整个页面的重新加载,故需要解决在spa模式的应用中网页在使用的过程中服务器已更新的资源不能被及时的获取的问题。
解决思路
- 标记版本:
- 在
vue.config.js
中每次编译生成一个版本号
- 使用
html-webpack-plugin
插件将版本号插入到index.html
的mate
标签
- 在
webpack
编译结束生成附带版本号的version.json
文件放置到服务器
- 检测版本
- 通过
document.getElementsByTagName("meta").buildVersion.content
获取浏览器已打开网页的版本号
- 通过不带缓存的
get
请求获取服务器存放的新版本号的version.json
- 刷新页面: 通过检测版本来提示或自动刷新页面获取最新的服务器资源
标记版本
- 配置
html-webpack-plugin
为index.html
插入编译版本号
| const HtmlWebpackPlugin = require("html-webpack-plugin"); |
| |
| const buildVersion = Date.now(); |
| console.log("当前编译版本: >>", buildVersion); |
| module.exports = { |
| configureWebpack: (config) => { |
| config.plugins.forEach((plugin) => { |
| if (plugin instanceof HtmlWebpackPlugin) { |
| plugin.options.version = buildVersion; |
| } |
| }); |
| }, |
| }; |
| |
- 在
index.html
插入mate
标签
| <meta name="buildVersion" content="<%= htmlWebpackPlugin.options.version %>"> |
- 创建用于生成
version.json
的webpack
插件build-version.js
| const pluginName = "BuildVersionWebpackPlugin"; |
| const fs = require("fs"); |
| const path = require("path"); |
| |
| |
| |
| |
| class BuildVersionWebpackPlugin { |
| constructor({ output = "./", version = Date.now() }) { |
| this.output = output; |
| this.version = version; |
| } |
| apply(compiler) { |
| compiler.hooks.done.tap(pluginName, () => { |
| console.log("webpack 编译完成,正在生成版本文件!"); |
| const outputPath = path.resolve(this.output, "./version.json"); |
| const versionJson = JSON.stringify({ |
| version: this.version, |
| }); |
| fs.writeFileSync(outputPath, versionJson, { |
| encoding: "utf-8", |
| }); |
| }); |
| } |
| } |
| |
| module.exports = BuildVersionWebpackPlugin; |
- 配置新建的webpack插件
| const BuildVersionWebpackPlugin = require("./build-version.js"); |
| |
| const buildVersion = Date.now(); |
| console.log("当前编译版本: >>", buildVersion); |
| module.exports = { |
| configureWebpack: (config) => { |
| ... |
| config.plugins.push( |
| new BuildVersionWebpackPlugin({ |
| output: "./dist", |
| version: buildVersion, |
| }) |
| ); |
| }, |
| }; |
检测版本
- 获取服务器存放的版本号
| async function _serverVersion() { |
| return await new Promise((resolve) => { |
| fetch("/version.json", { |
| headers: { |
| "cache-control": "no-cache", |
| }, |
| }) |
| .then((response) => { |
| try { |
| response.json().then((json) => { |
| resolve(json.version); |
| }); |
| } catch (error) { |
| resolve(0); |
| } |
| }) |
| .catch(() => { |
| resolve(0); |
| }); |
| }); |
| } |
- 获取浏览器本地页面的版本号
| function _currentVersion() { |
| return Number(document.getElementsByTagName("meta").buildVersion.content); |
| } |
- 版本号比较
| async function _inspector() { |
| let isConsistent = true; |
| const sv = await _serverVersion(); |
| const cv = _currentVersion(); |
| console.log(`检测到本地版本${cv}和服务器版本${sv}`); |
| console.log("本地&服务器版本是否一致:>>", (isConsistent = sv === cv)); |
| return isConsistent; |
| } |
| |
| export default async function() { |
| return await _inspector(); |
| } |
刷新页面
- 检测更新时机: 推荐在路由切换之后检测,或主要模块进入时检测
- 检测函数,具体的刷新逻辑按实际场景考虑
| versionCheck() { |
| inspector().then((isConsistent) => { |
| if (!isConsistent) { |
| const isReload = window.confirm( |
| "检测到本地版本和服务器版本不一致,点击确定更新页面 " |
| ); |
| if (isReload) { |
| window.location.reload(); |
| } |
| } |
| }); |
| } |
效果图

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)