Vite+Vue3項(xiàng)目版本更新檢查與頁面自動(dòng)刷新的實(shí)現(xiàn)方案
問題
使用 Vite 對(duì) Vue 項(xiàng)目進(jìn)行打包,對(duì) js 和 css 文件使用了 chunkhash 進(jìn)行了文件緩存控制,但是項(xiàng)目的 index.html 文件在版本頻繁迭代更新時(shí),會(huì)存在被瀏覽器緩存的情況。
在發(fā)版后,如果用戶不強(qiáng)制刷新頁面,瀏覽器會(huì)使用舊的 index.html 文件,在跳轉(zhuǎn)頁面時(shí)會(huì)向服務(wù)器端請(qǐng)求了上個(gè)版本 chunkhash 的 js 和 css 文件,但此時(shí)的文件已經(jīng)在版本更新時(shí)已替換刪除了,最終表現(xiàn)為頁面卡頓,控制臺(tái)報(bào)錯(cuò) 404。
解決思路
在每次打包生產(chǎn)代碼時(shí),在 public 目錄下生成一個(gè) version.json 版本信息文件,頁面跳轉(zhuǎn)時(shí)請(qǐng)求服務(wù)器端的 version.json 中的版本號(hào)和瀏覽器本地緩存的版本號(hào)進(jìn)行對(duì)比,從而監(jiān)控版本迭代更新,實(shí)現(xiàn)頁面自動(dòng)更新,獲取新的 index.html 文件(前提是服務(wù)器端對(duì) index.html 和 version.json 不緩存)。
第一步:配置服務(wù)器,禁止關(guān)鍵文件緩存
要實(shí)現(xiàn)版本對(duì)比,需確保 index.html 和后續(xù)生成的版本文件 version.json 不被瀏覽器緩存 —— 每次請(qǐng)求均從服務(wù)器獲取最新內(nèi)容。以 Nginx 為例,添加如下配置:
location ~ .*\.(htm|html|json)?$ {
expires -1;
}
第二步:開發(fā) Vite 插件,自動(dòng)生成版本信息
通過自定義 Vite 插件,在打包時(shí)自動(dòng)在 public 目錄下生成 version.json 文件,記錄當(dāng)前版本標(biāo)識(shí)(建議用時(shí)間戳,確保每次打包版本號(hào)唯一)。 TypeScript 版本插件(src/plugins/versionUpdatePlugin.ts)
// versionUpdatePlugin.ts
import fs from "node:fs"
import path from "node:path"
import type { ResolvedConfig } from "vite"
function writeVersion(versionFile: string, content: string) {
// 寫入文件
fs.writeFile(versionFile, content, (err) => {
if (err) throw err
})
}
export default (version: string | number) => {
let config: ResolvedConfig
return {
name: "version-update",
configResolved(resolvedConfig: ResolvedConfig) {
// 存儲(chǔ)最終解析的配置
config = resolvedConfig
},
buildStart() {
// 生成版本信息文件路徑
const file = config.publicDir + path.sep + "version.json"
// 這里使用編譯時(shí)間作為版本信息
const content = JSON.stringify({ version })
if (fs.existsSync(config.publicDir)) {
writeVersion(file, content)
} else {
fs.mkdir(config.publicDir, (err) => {
if (err) throw err
writeVersion(file, content)
})
}
},
}
}
JavaScript 版本插件(src/plugins/versionUpdatePlugin.js)
// versionUpdatePlugin.js
const fs = require("fs")
const path = require("path")
const writeVersion = (versionFile, content) => {
// 寫入文件
fs.writeFile(versionFile, content, (err) => {
if (err) throw err
})
}
export default (options) => {
let config
return {
name: "version-update",
configResolved(resolvedConfig) {
// 存儲(chǔ)最終解析的配置
config = resolvedConfig
},
buildStart() {
// 生成版本信息文件路徑
const file = config.publicDir + path.sep + "version.json"
// 這里使用編譯時(shí)間作為版本信息
const content = JSON.stringify({ version: options.version })
if (fs.existsSync(config.publicDir)) {
writeVersion(file, content)
} else {
fs.mkdir(config.publicDir, (err) => {
if (err) throw err
writeVersion(file, content)
})
}
},
}
}
第三步:配置 Vite,注入全局版本變量
在 vite.config.js/ts 中引入上述插件,同時(shí)定義全局版本變量 __APP_VERSION__(供前端對(duì)比使用),建議用當(dāng)前時(shí)間戳作為版本號(hào),確保每次打包版本唯一。
類型聲明(TS 項(xiàng)目必備)
若使用 TypeScript,需在 vite-env.d.ts 或 env.d.ts 中添加全局變量類型聲明,避免類型報(bào)錯(cuò):
// vite-env.d.ts declare const __APP_VERSION__: string
// vite.config.js or vite.config.ts
export default defineConfig((config) => {
const now = new Date().getTime()
return {
// ...
define: {
// 定義全局變量
__APP_VERSION__: now,
},
plugins: [
// ...
versionUpdatePlugin({
version: now,
}),
],
// ...
}
})
第四步:前端實(shí)現(xiàn)版本檢測(cè),觸發(fā)自動(dòng)刷新
利用 Vue Router 的全局前置守衛(wèi),在每次頁面跳轉(zhuǎn)前檢查版本 —— 對(duì)比瀏覽器端全局變量 __APP_VERSION__ 與服務(wù)器端 version.json 中的版本號(hào),若不一致則提示用戶并自動(dòng)刷新頁面(選擇前置守衛(wèi)是因?yàn)樘D(zhuǎn)失敗不會(huì)觸發(fā)后置守衛(wèi),可在報(bào)錯(cuò)前完成檢測(cè))。
const router = useRouter()
// 這里在路由全局前置守衛(wèi)中檢查版本
router.beforeEach(async () => {
await versionCheck()
})
// 版本監(jiān)控
const versionCheck = async () => {
if (import.meta.env.MODE === "development") return
const response = await axios.get("version.json")
if (__APP_VERSION__ !== response.data.version) {
ElMessage({
message: "發(fā)現(xiàn)新內(nèi)容,自動(dòng)更新中...",
type: "success",
showClose: true,
duration: 1500,
onClose: () => {
window.location.reload()
},
})
}
}
最后
到此這篇關(guān)于Vite+Vue3項(xiàng)目版本更新檢查與頁面自動(dòng)刷新的實(shí)現(xiàn)方案的文章就介紹到這了,更多相關(guān)Vite+Vue3項(xiàng)目版本更新檢查與刷新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
15 分鐘掌握vue-next函數(shù)式api(小結(jié))
這篇文章主要介紹了15 分鐘掌握vue-next函數(shù)式api(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
vue3?setup語法糖各種語法新特性的使用方法(vue3+vite+pinia)
這篇文章主要介紹了vue3?setup語法糖各種語法新特性的使用(vue3+vite+pinia),本文主要是記錄vue3的setup語法糖的各種新語法的使用方法,需要的朋友可以參考下2022-09-09
淺析webpack-bundle-analyzer在vue-cli3中的使用
這篇文章主要介紹了webpack-bundle-analyzer在vue-cli3中的使用,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-10-10
Echarts+VUE柱狀圖繪制細(xì)節(jié)并且屏幕自適應(yīng)完整代碼
柱狀圖(或稱條形圖)是一種通過柱形的長度來表現(xiàn)數(shù)據(jù)大小的一種常用圖表類型,這篇文章主要給大家介紹了關(guān)于Echarts+VUE柱狀圖繪制細(xì)節(jié)并且屏幕自適應(yīng)的相關(guān)資料,需要的朋友可以參考下2024-02-02

