vue-cli 打包后提交到线上出现 "Uncaught SyntaxError:Unexpected token <" 报错

前言: 项目使用vue-cli版本2.9.3 ,vue-router使用webpackChunkName实现按需加载.
图片描述

BUG描述:该报错在项目上线一段时间后,有用户反映页面无法正常游览 (后面以问题1/问题2区分)

问题1.导航点击无法正常跳转,刷新后恢复正常. console打印:Error:Loading chunk {n} failed.

报错截图图片描述

问题2.页面全白,并且刷新仍然无效. console打印:Uncaught SyntaxError:Unexpected token <

报错截图:图片描述

经过一番折腾,初步定位问题1在经过build/webpack.prod.conf.jschunkhash打包后的JS文件hash值会有变更,因为每次更新代码到线上都会删除旧的dist目录,将最新的dist目录copy上传提供后台更新. 在更新代码的这个过程用户停留在页面上,当用户在更新完后重新操作就会导致报错

图片描述

问题1解决方法:捕获路由报错. (思路来源:https://segmentfault.com/a/11... )

routers.onError((err) => {
  const pattern = /Loading chunk (\d)+ failed/g;
  const isChunkLoadFailed = err.message.match(pattern);
  if (isChunkLoadFailed) {
    let chunkBool = sessionStorage.getItem('chunkError');
    let nowTimes = Date.now();
    if (chunkBool === null || chunkBool && nowTimes - parseInt(chunkBool) > 60000) {//路由跳转报错,href手动跳转
      sessionStorage.setItem('chunkError', 'reload');
      const targetPath = routers.history.pending.fullPath;
      window.location.href = window.location.origin + targetPath;
    }else if(chunkBool === 'reload'){ //手动跳转后依然报错,强制刷新
      sessionStorage.setItem('chunkError', Date.now());
      window.location.reload(true);
    }
  }
})

问题2在Network查看js文件加载的时候发现某个js文件Response Headercontent-type异常,正常情况返回content-type: application/javascript. 但是有一个js响应的内容为HTML, js无法识别<符号导致抛出报错
图片描述
图片描述

问题2解决方法: 经过问题排查发现,vue-cli默认build后的文件名格式为js/[name].[chunkhash].js,每次npm run build后有改动的文件hash值都会改变,上传后Nginx无法找到最新上传的文件,所以返回了默认index.html里的内容,我们的文件后缀名是.js自然无法识别<html>这种标签符号,导致console抛出Uncaught SyntaxError:Unexpected token <,我尝试修改build/webpack.prod.conf.jsoutput输出文件名格式,目前问题已得到解决
图片描述

阅读 37.5k更新于 2018-11-12
 
16 条评论
 
Twittytop

问题2的解决办法里面,为什么把原来的'js/[id].[chunkhash].js'改为'js/[name]_[chunkhash].js'就有效呢,这种方式文件改变之后hash值不是也会变吗

1回复2019-02-25
Twittytop

@Twittytop 那这样的话不应该是一直会报错吗?为什么前期的时候nginx能正确解析,只有在网站更新代码后才发生解析错误呢?还有我觉得location.origin兼容性不是很好,可以修改为location.href = location.protocol + "//" + location.host + targetPath;

1回复2019-02-25
TouchFish(作者)

@Twittytop 因为nginx解析点号的时候误识别在[id].[chunkhash]后缀名,而不是.js后缀,导致content-type=text/html 将js代码解析成html代码

回复2019-02-25
TouchFish(作者)

@Twittytop 1.JS语法报错是不会继续往下执行的
2.当用户停留在旧的代码页面时,我们刚好更新了最新的代码上去,用户再操作,这个时候才会发生解析错误,主要是这个过程。
3.感谢提示,因为我们只考虑兼容主流游览器,当是就没考虑太多直接怼location.origin。^_^

回复2019-02-28
12345678

这还不简单吗,放新代码别把旧代码删了就行

回复2018-11-06
12345678

@12345678 @Sam_Lii 一般前端也就不到1M,除去不会变的图片、vendor等资源也就200K,发布100次才20M。服务端也可以写个简单的判断,只保留最新的两次发布,更老的才删

1回复2018-11-06
TouchFish(作者)

@12345678 这样服务器会累计过多废弃的文件

回复2018-11-06
回复2018-11-06
findxc

有个疑问,改为'js/[name]_[chunkhash].js'了之后,不是还是会找不到 js 文件吗?

回复2019-07-23
Lost_

你好,请问下第二个页面空白的问题,我改了文件名称之后,还是不行啊

回复2019-08-16
TorTorMore

您好,请问utils是如何配置的?

回复2020-06-05
TorTorMore

utils.封装能否分享

回复2020-06-05
豆浆

请问一下第二个页面空白的问题,我改了文件名称之后,还是不行啊

回复2020-12-22
系统错误

我遇到的是问题2
1.疯狂刷新的时候有小概率没问题
2.改了'js/[name]_[时间戳].js'没有效果

  1. 后端重启nginx解决
回复6 月 11 日
posted @ 2021-07-22 17:03  じ★ve花之谷  阅读(547)  评论(0)    收藏  举报