Vue項目中出現Loading chunk {n} failed問題的解決方法

最近有個Vue項目中會偶爾出現Loading chunk {n} failed的報錯,報錯來自於webpack進行code spilt以後某些bundle文件lazy loading失敗。可是這個問題的根本緣由沒有被找到,由於這個問題出現的偶然性過高了,並且有的手機上會出現,有的不會,用模擬器不會出現,用真機又會出現,不知道是網絡緣由仍是webpack的bug。在github、stackoverflow等各類地方也找不到緣由和解決方案,這是github上關於這個問題的討論: Loading chunk {n} failed #742,雖然最後仍是不了了之,可是你們能夠參考一下。javascript

這個問題出現機率比較小可是一旦出現就會致使頁面崩潰,因此仍是得解決,下面就貼出個人解決方案:前端

個人思路是既然找不到報錯的緣由那麼嘗試去捕獲這個錯誤並作容錯處理,有兩種實現,一是在服務端捕獲這個錯誤,一個是在前端捕獲。vue

服務端實現

報錯的緣由是某些js bundle沒有被找到,因此在服務端接收到獲取該js文件的請求時先判斷該js文件是否存在,若是存在直接返回js文件,若是不存在則返回一個提示信息給前端,讓前端處理。假設服務端用express做爲靜態文件服務器,代碼以下:java

app.all(/\.js$/, (req, res) => {
    const fileName = req.path.slice(req.path.lastIndexOf('/') + 1);
    const filePath = path.resolve(__dirname, './public/static/js/' + fileName);
    if (fs.existsSync(filePath)) {
        fs.sendFile(filePath);
    } else {
        res.setHeader('Content-Type', 'application/javascript; charset=UTF-8')
        res.setHeader('Accept-Ranges', 'bytes')
        res.setHeader('Vary', 'Accept-Encoding')
        res.setHeader('Transfer-Encoding', 'chunked')
        res.setHeader('Last-Modified', new Date().toUTCString())
        res.setHeader('Cache-Control', 'no-cache')
        res.send('window.serverRebuildHook && window.serverRebuildHook();')
    }
});

當js文件未找到時,經過res.send('window.serverRebuildHook && window.serverRebuildHook();')向前端返回一條消息,並執行前端定義的serverRebuildHook方法。webpack

接着咱們在前端實現serverRebuildHook方法:git

window.serverRebuildHook = function () {
  alert('服務器版本已更新,正在刷新本地緩存,請稍後...');
  location.replace(location.href);
}

方法很簡單,提示一下用戶服務端更新而後從新刷新當前頁面。github

這種實現是參考 github上的回答, 相對比較繁瑣,並且用戶體驗並很差,只能刷新當前頁面,不能跳轉到目標頁。web

前端實現

因爲項目裏面用到了vue-router,vue-router的錯誤處理函數 onError 是否是可以捕獲該錯誤呢?咱們來看一下官方文檔的說明:vue-router

image

當在渲染一個路由的過程當中,須要嘗試解析一個異步組件時發生錯誤。 徹底符合咱們場景,因此在onError方法中咱們實現以下代碼:express

router.onError((error) => {
  const pattern = /Loading chunk (\d)+ failed/g;
  const isChunkLoadFailed = error.message.match(pattern);
  const targetPath = router.history.pending.fullPath;
  if (isChunkLoadFailed) {
    router.replace(targetPath);
  }
});

當捕獲到Loading chunk {n} failed的錯誤時咱們從新渲染目標頁面,這種實現明顯更簡單和友好。

後續若是發現了致使Loading chunk {n} failed的本質緣由會再更新本文,歡迎關注!

感謝你們閱讀,另外,在這邊幫朋友推一個愛心衆籌,但願你們可以奉獻點愛心,朋友母親,身患直腸癌,目前在北京武警總醫院接收治療,可留言留下您的聯繫方式,往後感激你們!

clipboard.png

相關文章
相關標籤/搜索