在页面不刷新的情况下,通过用户行为,动态更新最新静态资源

459 阅读3分钟

前言

  • 文章是在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方法那里可以添加上一个弹窗,告诉用户当前版本为旧版本,是否需要更新。用户体验可能更好。