前言
- 文章是在vue框架之上讲解。
- 以下代码实现的功能是:在用户行为,在不刷新页面的情况下,通过校验版本号,来实现动态更新静态资源!
使用版本控制的原因
-
有一种情况,当用户一直停留的当前页面,正在使用中,或者用户一直打开着当前页,可能过个几分钟或几个小时再来使用,页面也不刷新。
-
上述情况中,如果前端发版了!,这时候,怎么通知用户呢?
-
这时候就需要版本控制,来实现动态更新内容了。
直接上代码
1.封装version.js脚本文件
const axios = require('axios')
const fs = require('fs')
// 在指定目录中添加version.json文件
const create = (path = 'public/version.json', version = (new Date().getTime()), result) => {
fs.writeFile(path, JSON.stringify({ version }), (err) => {
const isOK = !!err
if (result) { result({ isOK }) }
})
}
// 1.定义get方法,拿到远程服务器地址的版本号
const getVersion = async(path = 'version.json') => {
// 服务器文件路径,根据实际自定义
const url = `${window.location.origin}/${window.location.pathname.split('/')[1]}/${path}?_=${new Date().getTime()}`
try {
const { data } = await axios.get(url)
console.log('getVersion data', data)
return data
} catch (error) {
console.log(error, '请求版本号报错')
}
}
// 2.缓存版本号,根据实际情况需要,自定义字段名
const save = (version) => {
sessionStorage.setItem(window.location.pathname.split('/')[1] + 'Version', version)
}
// 3.检查是否有新版本(true:有新版本 false:没有新版本)
const isNewVersion = (version) => {
// 没值根据需要返回true或false
if (!version) { return false }
// 获取本地缓存的版本号
const storageVersion = sessionStorage.getItem(window.location.pathname.split('/')[1] + 'Version')
// 本地没有版本号,说明本机第一次加载,不算新版本
if (!storageVersion || storageVersion === 'undefined') { return false }
// 本地有版本号,进行对比
return `${version}` !== `${storageVersion}`
}
// 4.强制刷新当前网页,获取当前页面资源
const reload = () => {
window.location.reload(true)
}
// 拿到版本号-》是否执行更新的一系列操作
const get = async(path = 'version.json', isReload = true) => {
try {
// 1.拿到远程版本号
const data = await getVersion(path)
console.log('get data', data)
const version = data.version
// 2.判断是否有新版本
const isNew = isNewVersion(version)
// 3.保存版本号到本地缓存
save(version)
// 4.判断是否执行更新操作
if (isNew && isReload) reload()
return { version: version, new: isNew }
} catch (error) {
console.log(error, '对比版本号报错')
}
}
// 导出
module.exports = {
create,
getVersion,
save,
isNewVersion,
reload,
get
}
2.在vue.config.js中添加
const version = require('./src/utils/version.js') || []
if (process.env.NODE_ENV === 'production') {
version.create()
}
路由守卫中添加
router.afterEach(() => {
version.get()
NProgress.done()
})
public/index.html添加
这里的http-equiv是用于指定http协议相关的元数据,如头字段。content指定了实际的值。
//确保客户端每次都向服务器请求最新的资源,不会从本地缓存中获取。但是,这样会增加服务器的负载和响应时间,因为每次都需要向服务器请求资源。
<head>
<meta http-equiv="pragram" content="no-cache">
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="expires" content="0">
</head>
pragram、cache-control、expires这三个字段都是控制浏览器缓存行为的。pragram、expires已经淘汰。推荐用cache-control。
- no-cache 指令表示浏览器可以缓存该资源,但使用缓存之前必须先向服务器发送请求,以检查该资源是否已经被修改,如果没修改,服务器则返回304,浏览器使用缓存中的数据。如果资源已被修改,则服务器返回新的资源内容。
- no-store 指令表示浏览器不应该缓存该资源,每次都必须向服务器发送请求,以获取最新的资源内容,这种情况下,浏览器也不会将其保存在磁盘上。
- must-revalidate 指令表示每次都需要重新验证缓存是否过期。
实际添加下列代码就足够了
<head>
<meta http-equiv="cache-control" content="no-cache, must-revalidate">
</head>
以上配置完就可以实现单页面应用动态更新内容啦!
补充
自定义的reload方法那里可以添加上一个弹窗,告诉用户当前版本为旧版本,是否需要更新。用户体验可能更好。