SPA、单页面应用重新部署后,正在浏览的页面如何更新缓存?

因为更新频繁,且在使用高峰期更新发布,如果正在使用应用的用户并没有刷新页面,访问的都是缓存的旧页面,请问如何解决这个问题?

阅读 12.8k
5 个回答

这个问题我也思考了很久,目前没有找到比较完美的解决方案。事实上我们要把当前运行的代码更新到最新的,只能先更新index.html,而更新index.html目前我发现只能是刷新页面了。

目前临时解决方案有两个:

  1. 通过后端接口返回版本号判断是否有更新,有更新,就把页面刷新一下。这个事情可以放到切换路由的时候做,比如beforeEach。
  2. 在编译的时候自己生成一个js文件,然后前端用jsonp去请求这个js,判断是否有更新。有更新,就把页面刷新一下。这个事情可以放到切换路由的时候做,比如beforeEach。具体步骤如下:

在编译时候生成一个包含版本信息的version.js文件到dist目录,比如在webpack.prod.conf.js中:

var version = new Date().getTime()
var content = "getVersion('" + version + "')"

// console.log('开始创建版本文件...')
fs.writeFile(config.build.assetsRoot + "/version.js", content, function(err) {
  if(err) {
      return console.log(err);
  }
  // console.log("The file was saved!");
});

在路由文件中设置回调:

// 获取版本更新的jsonp回调函数
window.getVersion = version => {
  if((localStorage.frontendVersion && version !== localStorage.frontendVersion) || (window.frontendVersion && version !== window.frontendVersion)) {
    Loading.service(); // 启动全屏loading
    location.reload(); // 刷新页面
  }

  localStorage.frontendVersion = version; // 保存 以便下次使用判断
  window.frontendVersion = version; // 保存 以便下次使用判断
}

在router.beforeEach或router.afterEach发起jsonp:

var versionScript = document.createElement("script");
versionScript.src = location.origin + '/version.js?v=' + new Date().getTime();
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(versionScript, s);

可以自行封装一下。这两个最终效果都是用户在切换页面的时候,会发起一个请求,然后判断是否有更新,有更新就会刷新。

勉强解决了这个问题,期待有更好的方案。

使用axios请求'/index.html'文件 对比css和js文件的hash部分 如果不一致可以reload

时机可以在router的beforeEach或者其它

可以给html的url后边加上version或者时间戳等参数,如?version='1.1.0',这样每次发布后的url都是不同的,浏览器就会重新请求页面了

新手上路,请多包涵

楼主后来解决问题了吗?

@think2011 vue-cli3 vue.config.js配置这个fs.writeFile没生效

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏