本次项目地址:https://github.com/ht-sauce/vue3-pc-template
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" },
6、感谢阅读