Vue3+vite前端項(xiàng)目打包升級(jí)發(fā)版后,不手動(dòng)刷新祸轮,頁(yè)面跳轉(zhuǎn)文件找不到

產(chǎn)生原因:

使用vite對(duì)項(xiàng)目進(jìn)行打包兽埃,對(duì) js 和 css 文件使用了 chunkhash 進(jìn)行了文件緩存控制,但是項(xiàng)目的index.html文件在版本頻繁迭代更新時(shí)适袜,會(huì)存在被瀏覽器緩存的情況柄错。
在發(fā)版后,如果用戶不強(qiáng)制刷新頁(yè)面,瀏覽器會(huì)使用舊的index.html文件鄙陡,在跳轉(zhuǎn)頁(yè)面時(shí)會(huì)向服務(wù)器端請(qǐng)求了上個(gè)版本 chunkhash 的 js 和 css 文件冕房,但此時(shí)的文件已經(jīng)在版本更新時(shí)已替換刪除了,最終表現(xiàn)為頁(yè)面卡頓趁矾,控制臺(tái)報(bào)錯(cuò) 404耙册。

解決方案:

方案1

服務(wù)器發(fā)版時(shí),上一個(gè)版本的asset文件包不刪除
缺點(diǎn):隨著頻繁發(fā)版毫捣,服務(wù)器端前端項(xiàng)目文件會(huì)越來(lái)越多详拙,浪費(fèi)空間;若舊頁(yè)面的接口涉及到參數(shù)改動(dòng)等蔓同,會(huì)引起報(bào)錯(cuò)饶辙;流水線使用 docker 打包部署會(huì)變得非常麻煩。

方案2:

在每一次打包時(shí)斑粱,前端生成一個(gè)version版本號(hào)弃揽,路由跳轉(zhuǎn)時(shí)請(qǐng)求服務(wù)端的version.json數(shù)據(jù),與本地緩存的版本號(hào)做對(duì)比则北,從而監(jiān)控版本迭代變化矿微,實(shí)現(xiàn)自動(dòng)更新。
缺點(diǎn):在實(shí)現(xiàn)自動(dòng)更新的過(guò)程尚揣,沒(méi)辦法跳到指定的頁(yè)面涌矢,需要刷新后再重新點(diǎn)擊。但這個(gè)體驗(yàn)感可以忽略不計(jì)快骗。

具體操作步驟如下:

  1. 在項(xiàng)目目錄下創(chuàng)建build文件
// build\build.js
console.log("build > 文件開(kāi)始執(zhí)行娜庇!")
const fs = require("fs")
const path = require("path")

function getRootPath(...dir) {
  return path.resolve(process.cwd(), ...dir)
}
const runBuild = async () => {
  try {
    const OUTPUT_DIR = "dist"
    const VERSION = "version.json"
    const versionJson = {
      version: "V_" + Math.floor(Math.random() * 10000) + Date.now()
    }
    fs.writeFileSync(getRootPath(`${OUTPUT_DIR}/${VERSION}`), JSON.stringify(versionJson))
    console.log(`version file is build successfully!`)
  } catch (error) {
    console.error("version build error:\n" + error)
    process.exit(1)
  }
}
runBuild()
console.log("build > 文件執(zhí)行結(jié)束!")
  1. package.json中配置"postbuild": "node ./build/build.js"方篮,不同環(huán)境的構(gòu)建都要配置
 "postbuild": "node ./build/build.js",
 "postbuild:test": "node ./build/build.js",
 "postbuild:pre": "node ./build/build.js",
  1. 封裝本地緩存版本號(hào)的讀寫(xiě)方法
export const getAppVersion = () => {
  return localStorage.getItem(CacheKey.APP_VERSION) as string
}
export const setAppVersion = (version: string) => {
  localStorage.setItem(CacheKey.APP_VERSION, version)
}
  1. 寫(xiě)一個(gè)公共方法名秀,用于檢驗(yàn)服務(wù)端版本號(hào)是否更新,如有更新則自動(dòng)刷新
// 檢查服務(wù)端是否已經(jīng)更新藕溅,如果更新刷新頁(yè)面
export async function checkAppNewVersion() {
  if (process.env.NODE_ENV === "development") {
    return
  }
// 帶參數(shù)是為了拿到最新的數(shù)據(jù)
  const url = `/version.json?t=${Date.now()}`
  let res = null
  try {
    res = await axios.get(url)
  } catch (err) {
    console.error("checkAppNewVersion error: ", err)
  }
  if (!res) return
  const version = res.data.version
  const localVersion = getAppVersion()
  if (localVersion && localVersion == version) {
    return
  }
  if (localVersion && localVersion !== version) {
    ElMessage({
      message: "發(fā)現(xiàn)新內(nèi)容匕得,自動(dòng)更新中...",
      type: "success",
      showClose: true,
      duration: 1500,
      onClose: () => {
        setAppVersion(version)
        window.location.reload()
      }
    })
  }
  setAppVersion(version)
}
  1. router.beforeEach鉤子中,請(qǐng)求服務(wù)器version版本號(hào)
router.beforeEach(async (to, _from, next) => {
  await checkAppNewVersion()
  ...
  })
  1. 為了防止當(dāng)用戶在登錄頁(yè)時(shí)蜈垮,服務(wù)端更新了版本,所以用戶在輸入用戶名和密碼之后裕照,點(diǎn)擊登錄攒发,顯示登錄成功,正常是應(yīng)該直接跳到首頁(yè)晋南,但是此時(shí)跳轉(zhuǎn)前檢測(cè)到版本更新惠猿,所以會(huì)原地刷新一下獲取最新資源,導(dǎo)致頁(yè)面又恢復(fù)到了登錄之前的狀態(tài)负间,用戶需要重新登錄偶妖〗啵可以在App.vue中加入這個(gè)監(jiān)聽(tīng)
// 監(jiān)聽(tīng)頁(yè)面打開(kāi)顯示
document.addEventListener('visibilitychange', function () {
  // console.log('show ===>', document.visibilityState, !document.hidden)
  if (!document.hidden) {
    checkAppNewVersion()
  }
})

注意:

如果是采用pnpm打包,需要在.npmrc中配置:

enable-pre-post-scripts=true
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末趾访,一起剝皮案震驚了整個(gè)濱河市态秧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扼鞋,老刑警劉巖申鱼,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異云头,居然都是意外死亡捐友,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)溃槐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)匣砖,“玉大人,你說(shuō)我怎么就攤上這事昏滴『秭辏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵影涉,是天一觀的道長(zhǎng)变隔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蟹倾,這世上最難降的妖魔是什么匣缘? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮鲜棠,結(jié)果婚禮上肌厨,老公的妹妹穿的比我還像新娘。我一直安慰自己豁陆,他們只是感情好柑爸,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著盒音,像睡著了一般表鳍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上祥诽,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天譬圣,我揣著相機(jī)與錄音,去河邊找鬼雄坪。 笑死厘熟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播绳姨,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼登澜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了飘庄?” 一聲冷哼從身側(cè)響起脑蠕,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎竭宰,沒(méi)想到半個(gè)月后空郊,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡切揭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年狞甚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廓旬。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哼审,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出孕豹,到底是詐尸還是另有隱情涩盾,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布励背,位于F島的核電站春霍,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏叶眉。R本人自食惡果不足惜址儒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望衅疙。 院中可真熱鬧莲趣,春花似錦、人聲如沸饱溢。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)绩郎。三九已至潘鲫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肋杖,已是汗流浹背溉仑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留兽愤,地道東北人彼念。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像浅萧,于是被迫代替她去往敵國(guó)和親逐沙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容