概述
- 前端工程在打包发布之后,用户并不知道我们前端发版了,甚至根本不知道前端发版之后,怎么获取前端的最新版本,这样会造成很多因为前端没有更新所造成的功能不全,或者按照上一版本的数据提交给后端,造成数据错误的bug。
- 既然是前端版本的更新,那就是我们前端开发工程师的工作,是否能够不需要后端开发来些个接口,甚至还要建个新表或者往哪个倒霉的表里塞一条数据,然后不知道哪天哪个倒霉的后端就把数据删除了,然后报错。
- 首先前端版本得要有个放版本信息的地方,这个地方要在我们发版后必须通过网络请求来获取,还要在我们发版的时候去维护一下他;我最开始做的一版是通过数据字典来存放,我每发版一次,需要去数据字典中维护一次,但不是每个前端工程都有数据字典这个东西的;于是就重新找地方存放版本信息,想了半天,最终放在工程目录的 public 目录下,这个目录打包之后会被丢到 dist 目录下,然后部署到服务器之后,我们可以通过网络请求获取到这个目录下的文件,再把它弄成 json 文件,直接可以进行 json 序列化获取数据,剩下的就是开发了;
上代码
-
将模块单独抽成一个 version.js 文件
import axios from "axios"; import { MessageBox, } from 'element-ui' let interval = null // 记录当前时间并转成时间戳 const NOW = new Date().getTime(); // 轮询间隔时间,分钟为单位 const MINUTE = 30 // 从缓存中获取用户上次退出的时间戳 const LEAVE_TIME = parseInt(localStorage.getItem('LEAVE_TIME'), 10); // 判断是否为刷新,两次间隔在5s内判定为刷新操作 (!LEAVE_TIME || (NOW - LEAVE_TIME) <= 5 * 1000) && localStorage.removeItem('version') // 退出当前页面执行 window.onunload = () => { localStorage.setItem("LEAVE_TIME", new Date().getTime()); }; setTimeout(() => checkUpdate(), 1 * 1000) // 开启计时器 openInterval(); function openInterval() { interval = setInterval(() => checkUpdate(), MINUTE * 60 * 1000); } function checkUpdate() { // 使用 axios,不走响应拦截 axios({ url: location.origin + "/version.json" }).then((res) => { if (res.data && res.data.version) { let version = localStorage.getItem("version"); // 本地没有 version,表示刚进入系统,直接塞值 if (!version) return localStorage.setItem("version", res.data.version); if (res.data.version != version) { // 如果本地 version 跟获取的 version 不一致,则把最新的 version 保存本地,并重新加载页面 clearInterval(interval); // 有弹窗,则清除轮询 MessageBox.confirm("发现新版本, 是否更新?", "提示", { closeOnClickModal: false, closeOnPressEscape: false, showClose: false, confirmButtonText: "更新", cancelButtonText: `${MINUTE}分钟后提醒我`, type: "warning", }) .then(() => { localStorage.setItem('version', res.data.version) location.reload(); }) .catch(() => openInterval()); } } // 404 未找到该 JSON 文件,则停止轮询 }).catch(err => err.toString().indexOf('404') > -1 && clearInterval(interval)); } -
然后在 main.js 中引入该 js 文件,会直接运行;
继续追加功能,打包自动更新 version.json 里面的版本信息
-
上述功能完成后,版本更新就能用了,但是每次发版的时候,我们都需要去手动改 version.json 文件,麻烦,那能不能省掉这个步骤呢,当然可以;
-
想一下打包的过程,不就是将我们写的代码打包到 dist 目录下吗,dist 下面的所有文件都是通过 node 模块自动生成的,那自动修改 version.json 肯定也可以;
-
上代码:在 vue.config.js 文件中
/** * 通过 node 的 fs 模块对静态文件进行修改 */ // 开发环境不走逻辑,具体怎么判断,开发者自己定 if (process.env.ENV !== "development") { const fs = require("fs"); // 异步读取 version.json 文件 fs.readFile("./public/version.json", "utf8", (err, data) => { if (!err) { let obj try { obj = JSON.parse(data) obj.version++ } catch (error) { throw Error(error) } // 在 JSON 序列化成功才会去同步修改 version.json 文件内容 if (obj) fs.writeFileSync("./public/version.json", JSON.stringify(obj)) // 没有找到文件,抛出异常 } else throw Error(err) }) }