web端的项目,如何实时更新

329 阅读3分钟

项目背景

比如:项目新增了一些功能、或者修复某些bug,特别是修复bug,我们肯定希望当前正在访问的用户,可以立刻刷新页面。这样就可以偷偷的隐藏掉(只要bug不被发现,我就没错)。哈哈,言归正传,下面开始说解决方案。

我的思路

  1. 我们项目初始化一个配置文件(项目和版本信息)。
  2. 每次构建打包(npm run build/yarn build)的时候,读取配置文件,得到版本信息,然后增加版本号,生成新的配置文件(fs),保存到dist目录。 再把更新后的版本号信息,重新写入我们的原始配置文件。
  3. 定义一个函数,轮询请求这个dist文件夹下的配置文件(仅仅在生产环境),获取版本信息,首先保存版本信息到一个局部变量,后续每次请求,拿到的版本信息和该变量比较,不相等,则提示用户,有新版,给确认框确认?是否更新,是的话则调用location.reload

这里说下版本号,我是比较简单的实现(就是递增一个原始ID,初始化为0)。 version首次从0开发,后续每次生成配置文件时,去递增(++version),这样就可以保证版本号唯一。

项目根目录创建project.json

{
    "name":"project-name",
    "version":0
}

生成新配置文件和更新原始配置文件

let { version, name } = require('./project.json')
const path = require('path')
const fs = require('fs')
const content = `{
    "name":"${name}",
    "version":${++version}
    }`
fs.writeFile(path.resolve(__dirname, 'dist/version.json'), content, {}, (err) => {
    if (!err) {
        console.log('配置文件已经写入成功--->当前版本', version)
        fs.writeFile(path.resolve(__dirname, 'project.json'), content, {}, (error) => {
            if (!error) {
                console.log('已经更新原始配置文件--->当前版本', version)
            }
        })
    }
}) 

记得要去更新package.json文件的构建命令。 这里用webpack示例说明

  "scripts": {
    "build": "webpack --mode=production  --config webpack.prod.js && node generateVersionJson.js"
  },

算了,vite的也写下吧

  "scripts": {
    "build": "run-p type-check build-only && node generateVersionJson.js",
  },

更新版本的请求函数

import axios from 'axios'
import { ElMessageBox, ElMessage } from 'element-plus'
let isFirstLoad = true
let currentVersion
const managementVersion = () => {
    axios('/manual-project/dist/version.json', {
        headers: {
            'Cache-Control': 'no-cache',
        }
    }).then(res => {
        const { version } = res.data
        if (isFirstLoad) {
            isFirstLoad = false
            currentVersion = version
        } else {
            if (currentVersion !== version) {
                ElMessageBox.confirm('发现新版本,是否更新?',
                    {
                        confirmButtonText: '确认',
                        cancelButtonText: '取消',
                        type: '更新版本确认框?',
                    }
                ).then(() => {
                    ElMessage({
                        type: 'success',
                        message: '更新新版本了!!!',
                        onClose() {
                            location.reload()
                        }
                    })
                }).catch(() => {
                    ElMessage({
                        type: 'info',
                        message: '你取消了版本更新',
                    })
                })
            }
        }
    })
}
if (process.env.NODE_ENV === 'production') {
    setInterval(() => {
        managementVersion()
    }, 1000 * 60 * 30)
} 

这里侧重说下axios,因为我们默认请求version.json文件,浏览器针对这种不变的文件会做优化,把它在磁盘缓存起来(disk cache),所以我们请求文件的时候,默认情况下,它会一直读取缓存,导致我们更新失败,所以要设置下请求头(header)axios('url',{headers: {'Cache-Control': 'no-cache'}}),这样再去请求,每次都会请求服务器,而不是缓存了。

总结

看下来发现其实还是比较简单的,就是请求那里要设置下(这里有点坑),我代码调试,看它一直请求(dist cache),费了点时间,其他的都是有思路就行了。 如果大家自己测试下的话,可以按以下步骤来:

  1. git clone https://github.com/lzh-kf/manual-project.git
  2. git checkout master
  3. npm i
  4. 然后修改src/login/index.vue的代码,再去修改下src/updateVersion.js,把轮询改成1000 * 1 * 1
  5. 本地预览,cmd中执行: npm run preview,成功会在本地chrome浏览器打开项目。
  6. 再次修改src/login/index.vue的代码,然后执行npm run build,等它构建完成,你就可以看到步骤5打开的网页会有提示框,提醒你更新,至此完成。