暂时没法调bug,那就先写篇文章吧。
先说几个知识点,是这次项目需要的东西。
本次项目地址:github.com/ht-sauce/vu…
1、pre-commit:husky,lint-staged
最近vue3创建新项目package.json多了点东西叫做pre-commit
作用是:
项目要使用git进行代码提交时,使用叫pre-commit的git钩子,在调用git commit 命令时自动执行某些脚本检测代码,若检测出错,则阻止commit代码,也就无法push,保证了出错代码只在我们本地,不会把问题提交到远程仓库
配置:
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,vue}": [
"vue-cli-service lint",
"git add"
]
}
复制代码
2、浏览器缓存
除了我们平常可以操作的缓存数据之外,其实浏览器是会默默的给你缓存数据。像js文件或者图片,加载过一次之后浏览器就不会频繁获取。本地有就直接本地用了。但是引发了一个问题:
有时候我们前端项目发布了新版本,但是因为浏览器缓存问题。导致页面还是老页面这就比较麻烦,需要客户强制刷新一下才可以。而这种情况特别容易出现在页面只是微小改动的时候。
3、先实现一个npm run version,更新版本号
这里我们需要一点点的nodejs能力。fs文件操作模块
这里我就直接放代码了,懒得说。注意就是package.json部分增加修改
// updateVersion.mjs
import * as fs from 'fs/promises';
const versionApi = {
read: () => fs.readFile('./public/comjs/version.json'),
write: (str) => fs.writeFile('./public/comjs/version.json', str)
}
const packageApi = {
read: () => fs.readFile('./package.json'),
write: (str) => fs.writeFile('./package.json', str)
}
// 版本号修改
function updateVersionTool(resData) {
resData = JSON.parse(resData.toString())
const versionArr = resData.version.split('.')
versionArr[2] = Number(versionArr[2]) + new Date().getTime()
resData.version = versionArr.toString().replace(/,/g, '.')
return resData
}
// 修改版本
async function updateVersion() {
try {
// 修改package.json下面的版本号
const packData = await packageApi.read()
const pack = updateVersionTool(packData)
const version = pack.version
// 统一版本号,用package控制
const versionJson = await versionApi.read()
const versionData = JSON.parse(versionJson.toString())
versionData.version = version
// 写入版本文件
await packageApi.write(JSON.stringify(pack))
await versionApi.write(JSON.stringify(versionData))
console.log('最新版本号:' + version)
} catch (e) {
console.log(e)
return new Error(e)
}
}
updateVersion()
复制代码
这里我修改了两个文件,一个是本身的package.json文件,还有一个是public下面新了一个version.js文件。前一个问题不大,后一个才是这次版本更新的主角。而这个js更新文件的操作是为了每次打包的时候自动更新,不再需要手动取改一下版本号。特别是我们服务一般放在jekins等自动打包的服务的时候非常重要。
4、更新检测时机
之前看过不少文章,有首次加载项目的时候也有接口调用的时候。但是我想侵入性更小点,并且可插拔更高一些。所以我采用了Mixin方法。
1、首先建立一个glLoad.js文件并且实现逻辑
import { ajax } from '@/services/base/axiosAjax'
import vuex from '@/store'
let isReq = true // 是否允许请求
const GlLoad = {
created() {
this.checkVersion()
},
methods: {
async checkVersion() {
try {
const res = await this.getVersionJson()
const version = res.data?.version
if (!version) return null
const cacheV = vuex.state.version
if (cacheV !== version) {
console.log('更新版本', version)
window.location.reload(true)
vuex.commit('set_data', { version })
}
} catch (e) {
console.log('版本检测失败', e)
}
},
getVersionJson() {
switch (isReq) {
case true: {
setTimeout(() => {
isReq = true
}, 1000)
isReq = false
return ajax({ url: `/comjs/version.json?v=${new Date().getDate()}`, method: 'get' })
}
case false: {
return {}
}
}
},
},
}
export default GlLoad
复制代码
a、因为mixin是全局混入,所以所有组件在首次加载的时候都会去检测更新,但是为了避免接口异常频繁。我做了一层防抖处理。这样,一般页面也就1秒钟都加载完成了吧。然后1秒内就一次成功的检测。
b、这里千万注意要把版本号存入缓存,不然页面就无限刷新了。我这里是对vuex做了缓存处理的(vuex-persistedstate)
2、在main.js修改,并且混入
import 'normalize.css' // 默认css设置
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import components from './components'
import '@/theme/index.scss' // 主题样式导入
// 全局Mixin混入,用于检测更新版本
import GlLoad from '@/Mixin/GlLoad'
const app = createApp(App)
app.use(store)
app.use(router)
components(app)
app.config.globalProperties.$store = store
app.config.globalProperties.$router = router
app.mixin(GlLoad)
app.mount('#app')
复制代码
5、怎么自动更新呢?
其实看了上面大家都基本上知道了,我们只需要对package.json下面的script部分命令稍微修改下:比如vue-cli-service build变为:npm run version && vue-cli-service build
git预先检测部分
"gitHooks": {
"pre-commit": "lint-staged"
},
复制代码
改为
"gitHooks": {
"pre-commit": "npm run version && lint-staged"
},
复制代码