赞
踩
- 作者简介:大家好,我是文艺理科生Owen,某车企前端开发,负责AIGC+RAG项目
- 目前在卷的技术方向:工程化系列,主要偏向最佳实践
- 希望可以在评论区交流互动,感谢支持~~~
最近测试和用户频繁反馈,说经常会出现页面点不动了。然后每次都回复,刚发完版,刷新下就好了。但时间长了,就被怀疑是能力问题,因为其他项目为什么不这样呢?
先做一些准备工作,复盘一下当时的场景:
运行 pnpm create vite vue3-vite-router --template vue
在本地快速新建一个项目
进入项目目录中,运行pnpm i
安装依赖,安装成功后启动项目pnpm dev
, 启动成功后运行 pnpm build
进行打包。打包完成后根目录下会多出一个dist目录。运行 pnpm preview
预览构建后的项目。
页面可以正常打开:
页面窗口保持不变(不进行刷新等其他操作)。在AboutView.vue
文件中随便修改一点修改。再次运行打包pnpm build
和预览 pnpm preview
。在刚才的页面中点击 About 进行导航切换后,About页面对应的js文件请求失败了。
经过排查,是发版后js的文件名hash变了,原页面对应的html文件引用的js hash名称还是上一版本的,由于做了懒加载,所以点击跳转新页面时,对应的js文件不存在导致。懒加载的优化变成了事故,我冤枉啊~~~(我发誓:以后能跑起来绝对不优化)
为了证明自己的开发能力(掉发能力),针对vite项目调研了两种方案(纯前端方案,绝不麻烦后端):
翻看vite官方文档上发现了一个简单的办法:当vite加载动态导入失败时,会触发 vite:preloadError
事件。可以使用这个事件进行处理。
在main.js中增加以下代码:
// 其他代码
window.addEventListener('vite:preloadError', (event) => {
console.log('检测到有新版本,5秒后即将刷新...');
setTimeout(() => {
window.location.reload() // 例如,刷新页面
console.log('页面已更新为最新版本...');
}, 5000)
})
先执行 pnpm build
和pnpm preview
,刷新页面。然后随意修改AboutView.vue的代码,重新执行 pnpm build
和pnpm preview
,点击About后,js请求异常,会触发vite:preloadError事件,然后执行回调中的刷新逻辑。
总结:这个方法比较简单,但是只能应用在路由切换的场景中。
还有一种场景是无路由切换时,代码未及时进行更新。对我们的项目来说,都是在晚上发布,如果有版本更新,运维同学会在群里及时同步测试和产品同学。如果需要解决,需要进行轮询操作。具体请参考:2种纯前端检测版本更新提示
目测最佳的时间方案为:
vite打包构建时生成版本号json文件,并将json文件保存到构建好的静态资源目录中。
路由变化时执行:对比json文件中的版本号与缓存中是否一致。若一致,则进行弹窗提示用户进行刷新。
相关代码参考了这篇文章:vite前端版本升级,刷新页面
// src/plugins/refreshPlugin.js import path from "path"; import fs from "fs"; // 将文本内容写入指定文件中 const writeVersion = async (versionFile, content) => { fs.writeFile(versionFile, content, (err) => { if (err) throw err; }); }; export default (options) => { // 声明配置文件路径 let configPath; return { name: "refreshVersion", configResolved(resolvedConfig) { // 保存配置文件的路径,后用 configPath = resolvedConfig.publicDir; }, async buildStart() { // 生成版本信息文件路径 const file = configPath + path.sep + "version.json"; // 采用编译的当前时间作为每个版本的标识 const content = JSON.stringify({ version: options.version }); if (fs.existsSync(configPath)) { // 如果文件路径已存在,直接写入文件 writeVersion(file, content); } else { // 如果文件路径不存在,先创建文件夹,然后再写入文件 fs.mkdir(configPath, (err) => { if (err) throw err; writeVersion(file, content); }); } }, }; };
// vite.config.js import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import refreshPlugin from './src/plugins/refreshPlugin.js' const now = new Date().getTime(); // 定义一个时间戳 // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), // 引入插件 refreshPlugin({ version: now }) ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }, // 缓存全局的版本时间戳 define: { __APP_VERSION__: now, } })
router/index.js // 其他代码 // 路由变化时执行 router.beforeEach(async (to, from, next) => { await versionCheck() // 版本比对 next() }); // 版本比对,全局缓存的版本 与 版本号文件读取结果 不同时,说明有新版本,5秒后自动刷新 const versionCheck = async () => { if (process.env.NODE_ENV === 'development') return const response = await axios.get('version.json') if (__APP_VERSION__ !== response.data.version) { // 有新版本,刷新页面 console.log('有新版本,5秒后自动刷新页面'); setTimeout(() => { window.location.reload() }, 5000) } }
与第一种方案相同操作,先后运行两次 pnpm build
和 pnpm preview
。结果显示,第二次build后,路由切换自动刷新完成。
总结:本文提出了vite项目中版本变化的刷新问题,通过监听vite异常事件事件和维护比对发布版本时间戳两种方案,成功解决了自动刷新问题,并展示了demo相关代码和运行结果。
日拱一卒,功不唐捐。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。