详解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,虽然最后还是不了了之,但是大家可以参考一下。

这个问题出现概率比较小但是一旦出现就会导致页面崩溃,所以还是得解决,下面就贴出我的解决方案:

我的思路是既然找不到报错的原因那么尝试去捕获这个错误并做容错处理,有两种实现,一是在服务端捕获这个错误,一个是在前端捕获。

服务端实现

报错的原因是某些js bundle没有被找到,所以在服务端接收到获取该js文件的请求时先判断该js文件是否存在,如果存在直接返回js文件,如果不存在则返回一个提示信息给前端,让前端处理。假设服务端用express作为静态文件服务器,代码如下:

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方法。

接着我们在前端实现serverRebuildHook方法:

window.serverRebuildHook = function () {
 alert('服务器版本已更新,正在刷新本地缓存,请稍后...');
 location.replace(location.href);
}

方法很简单,提示一下用户服务端更新然后重新刷新当前页面。

这种实现是参考github上的回答, 相对比较繁琐,而且用户体验并不好,只能刷新当前页面,不能跳转到目标页。

前端实现

由于项目里面用到了vue-router,vue-router的错误处理函数 onError是不是能够捕获该错误呢?我们来看一下官方文档的说明:

当在渲染一个路由的过程中,需要尝试解析一个异步组件时发生错误。 完全符合我们场景,所以在onError方法中我们实现如下代码:

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的本质原因会再更新本文,欢迎关注!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 解决vue点击控制单个样式的问题

    既然是控制单个样式,我们的html里面的内容一定是v-for="":渲染出来,一定要养成一个好习惯,v-for="(item,index) in items";index就是我们所说的索引. <div class="border" v-for="(item,index) in tolos" :key="index"> 我做的项目类似于微信朋友圈,弹出赞与评论按钮,点击一个全体都会弹出:我们要解决

  • Vue中使用 setTimeout() setInterval()函数的问题

    在vue点击事件调用函数的过程中,想通过 setTimeout() setInterval()函数来延迟修改参数时,发现函数没有执行,控制台也没有报错,代码如下: var vm_target = new Vue({ el: '#vm_target', data: { clickSubmitBtn:false }, methods:{ myFunc:function(){ setTimeout(function(){ this.clickSubmitBtn = true; //此处修改data中的

  • 如何解决vue2.0下IE浏览器白屏问题

    公司新开发的项目需要兼容到IE9+ 就在index.html页面加入 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 不起作用 总结方法: 1.兼容IE9/IE10可能会遇到语法或者 Promise错误,安装 babel-polyfill npm install babel-polyfill 2.在页面入口配置main.js中引入 babel-polyfill import("babe

  • vue 解决循环引用组件报错的问题

    做项目时遇到使用循环组件,因为模式一样,只有数据不一样.但是按照普通的组件调用格式来做时报错,错误信息为Unknown custom element: <pop> - did you register the component correctly? For recursive components, make sure to provide the "name" option. 查询了官方文档,还有其他的资料,发现是循环调用组件时,组件比vue实例后创建,官方文档里写组件

  • 解决vue同一slot在组件中渲染多次的问题

    Q:今天写公共组件的时候碰到一个奇葩的情况,slot内部需要再次调用slot,这就会导致同一slot在组件中渲染多次引发的bug A:把把父组件需要传入的dom结构作为props属性传递给slotRender,保证出来的dom结构不相同(尽管它们都是同一vnode渲染出来的) 定义一个渲染slot的组件 子公共组件调用 父公共组件调用 以上这篇解决vue同一slot在组件中渲染多次的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • Vue下拉框回显并默认选中随机问题

    今天做vue的页面下拉框回显问题,回显数据是随机的,好奇怪,虽然多刷新 几下就可以了, 但是这个问题还是存在的,后来发现问题是 回显中的数据是两次请求,因为网络问题两次说不定哪个就请求的快一些, 因为调用的对象不一样,所以可能会不同,改为相同的之后,发现第一次请求的时间始终比第二次时间短一些,达到想要的效果 总结: 1.因为第一次加载下拉框列表的时候,请求列表中所有数据和列表默认回显数据不同,所以会出现被刷新,而出现回显随机问题,,, PS:vue 运用ElementUI,做select下拉框回

  • Spring boot 和Vue开发中CORS跨域问题解决

    跨域资源共享CORS(Cross-origin Resource Sharing),是W3C的一个标准,允许浏览器向跨源的服务器发起XMLHttpRequest请求,克服ajax请求只能同源使用的限制.关于CORS的详细解读,可参考阮一峰大神的博客:跨域资源共享CORS详解. 1. 遇到的问题: 我用spring-boot 做Rest服务,Vue做前端框架,用了element-admin-ui这个框架做后台管理.在调试的过程中遇到了如下错误: Preflight response is not

  • vue项目开发中setTimeout等定时器的管理问题

    一.问题来源. 在项目中,我们经常有这样的需求,一个页面初始化后,需要不断的去请求后端,来获取当前某个记录的最新状态. 显然,这个可以用setTimeout以及回调中继续setTimeout来实现. 我们假设定时器是在页面#/test/aaa上创建的. 但是,会遇到以下两个问题,我从#/test/aaa   这个页面切换到  #/test/bbb页面后如果停留在#/test/bbb,定时器还在跑. 其次,如果我不断在#/test/aaa 和 #/test/bbb两个页面之间不断的切换,而且切换时

  • 解决vue 引入子组件报错的问题

    错误信息: Do not use built-in or reserved HTML elements as component id: header 源码: <script> import header from "./components/header" import aside from "./components/aside" import footer from "./components/footer" export de

  • 解决vuejs项目里css引用背景图片不能显示的问题

    解决:build->utils.js里,修改:增加 publicPath:'../../', if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, publicPath:'../../', fallback: 'vue-style-loader' }) } else { return ['vue-style-loader'].concat(loaders) } 以上这篇解决vuejs项目里css引用背景图片

  • 解决Vue.js父组件$on无法监听子组件$emit触发事件的问题

    最近学习vuejs看例子中用$on无法监听子组件$emit触发事件: 使用版本 vue.js 2.2.5 参考文献 1.vuejs API 2.解决实例 问题分析 1.之前写的自定义组件事件触发为this.$emit("myclick",this.todo.text);,这样this指的是todo-item的每一项,而最后vm.$on监听的是app组件,也就出说监听的是父节点,而触发的是子节点,故监听不到这个事件的. 解决思路 1.将触发事件放在父节点上触发,就可以监听到触发的事件了,

随机推荐