關于Vue Loading chunk {n} failed的一些思考
更新時間:2020-06-02 14:52:43
0x1 問題
測試偶爾會出現這個問題,遂提出一個bug
,從bug
字面意思來看,有一個js
的塊加載失敗了。丟失了一個${domain}/js/chunk-${hash}.js
。
為什么會丟失?
為什么會偶發?
同類問題
Vue項目中出現Loading chunk {n} failed問題的解決方法
本文大量引用了17khba在點擊切換路由的時候,有時候會報錯的回答。
0x2 偶發性原因
前提:部署方式為刪除上一次構建的資源文件,替換成新的打包文件。
- 新版本部署前,有用戶正在你的網頁中
- 然后你部署了新版本,而且是刪除原有資源,比如 hash 為
bgt78d
的資源不見了,但此時用戶的index.html
模板中還是記錄的bgt78d
的資源地址 - 這時用戶在他現有的頁面中進行路由切換,前端路由切換
- 這不會觸發去重現獲取
index.html
,所以老的index.html
中的 chunk 信息生效 - 這個時候如果訪問已經訪問過的路由,這些路由中的 chunk 已經被瀏覽器緩存,路由(頁面)能正常,雖然它可能使用的是過時的資源(就你上一個版本發布的資源)
- 但是當請求之前沒有請求過的路由,因為懶加載的關系,這些路由對應的組件 chunk 沒有緩存,根據老的 chunk 對應信息,去請求老的靜態資源,而老的靜態資源又已經由于你的部署頂替掉了,于是出現找不到的問題
- 刷新就可以,因為刷新重現獲取了一遍 html 文檔,chunk 對應信息也就刷新了
0x3 簡單解決思路
上面也提到了刷新頁面,但是僅僅捕獲到錯誤就刷新,很可能出現死循環,因為瀏覽器或者類似于Nginx
緩存設置的原因,瀏覽器不一定每次刷新去獲取新的index.html
。
所以結合重試次數和重試間隔來重試會比較好
0x4 更好的解決思路
- 構建的時候靜態資源路徑帶上版本信息,這個有很多方法
- 比如路徑中攜帶,比如原來請求
/static/js/balabal.[hash].js
,現在/[version]/static/balabal.[hash].js
- 比如路徑中攜帶,比如原來請求
- 部署的時候不用頂替部署,而是保留老版本,有很多方式,比如
- 如果是裸機部署,可以在 web 服務器根目錄下,新建 version 對應的目錄,然后部署到這個目錄
- 如果是 docker 容器頂替部署,可以在構建前端的時候將前端資源打成 tar 包上傳到某個地方,這樣在打包新版本的 docker 鏡像的時候,可以拉取上一個版本的 tar 包,也打包到鏡像中,這樣 docker 中也能有兩個版本的資源,通過版本路徑區分下
- 這樣的情況下,原有頁面的用戶還是會訪問到老的資源,雖然可能版本落后,但是不會出錯,部署后新打開的頁面就會訪問新的資源
PS.如果不想暴露 version,可以把 version 做一個 hash 或者混淆
0x5 實現
查看Vue-cli配置文檔,
assetsDir
Type:
string
Default:
''
放置生成的靜態資源 (js、css、img、fonts) 的 (相對于
outputDir
的) 目錄。提示
從生成的資源覆寫 filename 或 chunkFilename 時,
assetsDir
會被忽略。
只需要給assetsDir
設置一個版本號文件夾,每次發布新版的時候,不刪除這個文件夾就行。可以選擇性的保留最近幾次版本的靜態資源文件。
使用 npm 版本號管理進行配合。
${app}/vue.config.js
const { version } = require('./package.json')
module.exports = {
// 放置生成的靜態資源 (js、css、img、fonts) 的 (相對于 outputDir 的) 目錄。
assetsDir: `./${version}`,
...
}
打包命令加上--no-clean
。作用是不清除上次打包生成的dist
目錄。
vue-cli-service build --no-clean
0x6 結論?
問題到這里基本已經解決了,不過仍然出現了一些可以優化的地方。比如我沒有清除上次打包的dist
目錄,如果在${app}/public
目錄下引入的一些靜態資源后期版本已經刪除了,由于我們沒有刪除dist
目錄,不需要的資源仍然存在部署的服務器上。、
如果有很好的方案歡迎指出或者討論。謝謝你的閱讀~??
關于我
SunSeekerX,前端開發、Nodejs開發、小程序、uni-app
開發、等等
喜歡探討技術實現方案和細節,完美主義者,見不得bug
。
Github:https://github.com/SunSeekerX
個人博客:https://yoouu.cn/
個人在線筆記:https://sunseekerx.yoouu.cn/