1. 程式人生 > 其它 >vue 路由懶載入和多層巢狀路由導致線上的專案有時出現載入css,js檔案Loading chunk xxx field失敗的情況

vue 路由懶載入和多層巢狀路由導致線上的專案有時出現載入css,js檔案Loading chunk xxx field失敗的情況

技術標籤:vuevue

這是我真實專案中遇到的,現在記錄下,問題比較多,我們一一展開來。

前言:下面這些問題的前提是你線上的專案一開始進去是正常的,如果一開始進去就報資源地址錯誤,那可能是publicPath的配置有問題,無非是這三種中的一種,publicPath:" ./ " ,publicPath: "/",publicPath:"資料夾/"。根據實際情況配置就好了。

問題一:vue路由懶載入導致線上環境偶爾出現 Loadingchunkxxxxfailed的錯誤。

vue專案使用路由懶載入的原因是為了減少首屏開啟的時間太長而引入的。如component:()=>import("@/views/User/User"),在路由懶載入下會有一種情況。就是你的專案程式碼更新了,釋出到線上,但是沒用的頁面由於他並沒有手動重新整理,有時點選某個選單欄的時候就報了上面圖片這個錯誤。原因是沒法打包上傳的程式碼hash值一般都不同,而使用者的頁面還沒重新整理,資源路徑指向還是原來的,所以就報了以上的錯誤。一般使用者重新整理頁面後這個問題就解決了。但是我們不可能說沒釋出一個新版本就通知使用者一遍,這是不存在的!那麼我們怎麼處理這個問題。有兩種方法:

(1)把懶載入改為直接引入,就是直接import xxx from xxxx,缺點就是使得首屏載入的時候時間變長,自己根據實際取捨。

(2)在路由檔案里加上路由錯誤處理,如果使用下面的辦法還是有問題的話,還是乖乖不要使用路由懶載入了。

/ 解決Loading chunk (\d)+ failed問題
router.onError((error) => {
  const pattern = /Loading chunk (\d)+ failed/g; //這個是網上大部分遇到的
  const cssPattern = /Loading CSS chunk (\d)+ failed/g; //這個是我實際專案中遇到的
  const isChunkLoadFailed = error.message.match(pattern) || error.message.match(cssPattern);
  if (isChunkLoadFailed) {
      // 用路由的replace方法,並沒有相當於F5重新整理頁面,失敗的js檔案並沒有從新請求,會導致一直嘗試replace頁面導致死迴圈,而用 location.reload 方法,相當於觸發F5重新整理頁面,雖然使用者體驗上來說會有重新整理載入察覺,但不會導致頁面卡死及死迴圈,從而曲線救國解決該問題
      location.reload();
      // const targetPath = $router.history.pending.fullPath;
      // $router.replace(targetPath);
  }
});

問題二:多層巢狀路由導致watch,computed,transtion過渡失效(實際不是失效,下面詳解)

我們專案一般會使用到巢狀路由,不過大多就一層巢狀路由,就是父 ->子,如果2層以上的巢狀路由,既xx ->爺 ->爸 ->兒子。假如 爸 下面有多個兒子,然後你想在 “爸” 這個元件裡監聽路由變化,好對各個兒子進行相應的邏輯處理。但是這時你會發現watch路由是沒有用的,watch沒有進去,又或者你用computed監聽路由,在裡面列印也是沒列印的。難道是watch和computed都失效了嗎,明明我切換頁面路由變化了呀。

其實並不是watch和computed失效了,你再看看結構,爸的上面是至少來由爺爺的,也就是說當你兒子路由變化的時候,爺爺那裡的<router-view />也是過載了“爸”這個元件,那麼“爸”這個元件的生命週期就有執行了一遍,既重新繪製渲染了,所以watch裡沒有列印,不過你想測試,只需在 "爸"這個元件裡的created或者mounted裡新增console.log(),你就可以發現當 “兒子”路由變化的時候,“爸”的created等生命週期又執行了。所以如果你這時想在“爸”這個路由裡新增transtion路由動畫是沒效果的,因為監聽不到路由變化。

解決辦法:把父這一層路由放出去和爺爺這一層路由同級,由於同級所以沒有巢狀關係,這也就意味著爸如果想使用爺爺裡面的東西,就得單獨引入該元件。同時可以考慮“兒子”元件不用<router-view>來承載,可以用v-if來判斷元件的顯示隱藏來代替<router-view>

問題三:路由懶載入和多層巢狀導致線上專案偶爾找不到資源,如Loadingchunkxxxxfailed的錯誤。