前端项目发版后用户需要手动刷新页面获取的解决方案 您所在的位置:网站首页 如何强制刷新浏览器 前端项目发版后用户需要手动刷新页面获取的解决方案

前端项目发版后用户需要手动刷新页面获取的解决方案

2023-08-07 16:28| 来源: 网络整理| 查看: 265

背景

我们的项目是后台管理系统,框架是Vue,构建工具是Webpack。

问题

每一次修改代码后打包发布到生产环境后,用户需要手动刷新才能获取到最新的代码。

原因

Webpack打包之后会根据文件内容生成一个hash值,然后再按照[name].[hash].js的格式生成文件名;

然后再根据文件的路由对应关系生成一个runtime.[hash].js的文件,这个文件会监控浏览器的路由变化去服务器加载对应的js文件。

而runtime.[hash].js文件是放在index.html中,在开始进入系统时已经加载。

所以当服务器重新发版之后,生成的文件会出现hash值改变,这时候当用户跳转路由时,请求加载的文件名在服务器上已经找不到了,就会报错:Loading chunk [name].[hash].js failed

方案

思路:既然能监控到加载js的错误信息,那么就可以在处理错误信息的代码中加入刷新页面的功能,让页面自动去刷新页面,然后再获取最新的runtime.[hash].js文件,用户再次点击时就可以正常访问了。

按照思路,分为以下2步:

找到处理错误信息的代码,加入刷新页面逻辑

经过几番查找,处理错误信息的代码在runtime.[hash].js中,如下:

var u = new Error; d = function(a) { o.onerror = o.onload = null, clearTimeout(b); var c = r[e]; if (0 !== c) { if (c) { var t = a && ("load" === a.type ? "missing" : a.type), f = a && a.target && a.target.src; u.message = "Loading chunk " + e + " failed.\n(" + t + ": " + f + ")", u.type = t, u.request = f, c[1](u) } r[e] = void 0 } }

难点在于,runtime.[hash].js是由webpack单独生成的,我们不能通过项目中的代码来修改,而且暂时没有找到通过配置的方式来修改。

目前的临时解决方案:

通过Loading chunk关键字在webpack模块中找到了对应的文件,文件地址:webpack/lib/web/JsonpMainTemplatePlugin.js,找到处理错误代码,并添加刷新页面代码:

Template.indent([ "if(chunk) {", Template.indent([ "var errorType = event && (event.type === 'load' ? 'missing' : event.type);", "var realSrc = event && event.target && event.target.src;", "error.message = 'Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';", "error.type = errorType;", "error.request = realSrc;", "chunk[1](error);" ]), "}", "location.reload(ture)", // 在此处添加刷新页面代码 "installedChunks[chunkId] = undefined;" ]),

重新执行npm run build命令就可以了

问题的来了,自动布署时会重新拉取webpack包,还是不能生效。

解决方案就是自己Fork webpack项目,修改以上代码后,再自己发布一个npm包,

然后将项目中的webpack引用名改成自己的npm包名,这样就可以了,缺点就是后续的升级比较麻烦。

刷新页面时,取消缓存,获取最新的文件

自动刷新解决了,发现浏览器并没从服务器上拉取文件,原因就是浏览器缓存了。

解决方案:在文件请求路径添加参数,参数值设置为hash值,比如:

怎么配置呢?

找到webpack的output,设置成如下:

output: { path: OUTPUT_PATH, publicPath: '/', filename: 'static/js/[name].[chunkhash:8].js?t=[chunkhash:8]', chunkFilename: 'static/js/[name].[chunkhash:8].js?t=[chunkhash:8]' } 优化

按照目前的解决方案,确实可以实现不再需要手动刷新获取最新的资源,但是有个问题就是刷新之后并不会跳转到用户点击的页面,还是停留在当前页面,需要再点击一次才到跳转。

所以我们可以在刷新之前,弹出一个确认框,告知用户服务器发版或升级了,需要刷新页面才能获取最新的资源。用户点击确认之后再进行刷新操作。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有