关于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/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。