阅读 395
webpack 之 Loading chunk x failed

webpack 之 Loading chunk x failed

这是我参与更文挑战的第 3 天,活动详情查看: 更文挑战

Lynne,一个能哭爱笑永远少女心的前端开发工程师。身处互联网浪潮之中,热爱生活与技术。

问题

看书时看到,在配置入口文件时 webpack 可以打包抽取 vendor 并进行客户端缓存加快整体渲染速度。

联想到之前在开发后进入测试环节时,明明我本地是没有问题的,但相同的代码在生产环境下打包部署到测试环境时,在别人的电脑上却出现了 loading chunk xx failed 的错误,甚至有时候刷新也无效。但在我的电脑和测试过的 mac 上都没有问题,好像的确 windows 的偶现频率更高...

Fix bug

虽然这个 bug 是偶现的,当时也是提心吊胆了一番,如今再次回想起,也还是想搞清楚具体原因。废话不多说,根据我一番调查和思考,直接放上两种最可能的、也最主要的(还有最最离谱的)原因及其解决方案。

最常见的一种 - 路由懒加载 + 缓存

项目开发时上传测试环境后会出现,当我们打包后某些js文件会改变,再上传到服务器后,由于浏览器缓存问题,用户在访问的时候还会再访问之前的js文件。也就是说最新打包的js文件改动了,但使用了浏览器缓存的旧的index.html读取的还是旧的chunk,这种情况可以通过刷新页面解决,那就好办多了。

在路由懒加载的情况下,访问当前应用进行路由跳转时都是实时动态的从服务器上拉取相应模块的js文件,这时候改完代码打包上线,路由跳转的时候由于页面并未刷新,所以还是访问的原来的文件名,这是就会出现找不到模块的错误。推荐解决方案是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);
  }
});
复制代码

但从开发反馈来看不是完全生效,所以才有了我们后面的方案呀!

最离谱的一种 - 运营商劫持

最后看完这种情况分析,感觉就简直离谱,作者好不容易排查出这个问题,解决方案却很简单 --- >使用https加密数据传输,防止请求篡改。

细节不多讲,因为具体可以参考这篇文章 - webpack之Loading chunk x failed

如果使用了 HTTPS还是有这样的情况,匿名读者反馈是打的包名以16开头容易被劫持,我???

总结

简单总结,以上是遇到这种报错的两个主要解决思路,但由于偶现简单清个缓存或者重新打包就避过了这个问题。而可能的原因不止一个,所以好像并没一劳永逸彻底解决这个报错会偶现的问题。在这个issue中的讨论最后也没有给出一个大家都认可的明确的答案...

https避免运营商劫持这个方案其实我还没有验证过(别打我...),如果后面遇到的话还要看下。

唠嗑

本来今天是想讲讲 webpack 2.x 中是如何借助 uglify 实现对标记代码进行清除后压缩的,结果遇到这么个问题又研究半天(最初遇到这个报错时的各种 google 的经历在我再次 google 一遍后才想起来...)

好了明天的内容预定好了,相信我不会鸽...

参考资料

文章分类
前端
文章标签