记录一次老平台改造通知用户刷新页面,纯前端实现

记录一次老平台改造通知用户刷新页面,纯前端实现

方案概述

背景

前端构建完上线,用户还停留还在老页面,用户不知道网页重新部署了,跳转页面的时候有时候js连接hash变了导致报错跳不过去,并且用户体验不到新功能。
客户打网页后,长时间不关闭对应标签页,也不刷新页面(在中后台管理项目挺常见的),且期间服务器页面有更新,经常出现

现状

目前我们或者合作商情况有如下几种情况:

  1. 目前路由hash模式,也就是锚点的形式,造成缓存问题;
  2. 在用户无感知的情况下升级平台,而用户因历史访问,无法获取最新的资源,造成用户体验差;
  3. 升级平台后,可能出现资源访问不到情况;

在现有的平台体系中,由于现在平台架构趋于一个成熟的阶段,基于改动最小、影响最小的原则的情况下,来设计适合目前平台的一套合理的方案解决这些问题;

问题本质

目前平台采用的hash的模式处理,也就是我们常说的锚点的形式,改方式的和history的不同是,histroy 的每次url变化都会像后端服务器请求,会重载页面index.html,这就是单页面history 需要在服务器上配置重定向到index.html的原因;而我们平台使用hash的形式,这种形式,只有在首次加载或者刷新页面的时候会重新请求服务器的index.html,相应的资源在这种情况下才会加载新的资源,url 地址变换并不会向history一样请求服务器,而是前端自主完成,所以在第一次访问完成之后,主要的js已经加载啦,后面操作都是根据主js的相关解析,请求相应的资源!所以在这种情况更新系统 造成资源是旧的或者资源请求不到的情况!

方案设计

前提

基于目前的平台框架,一切改动不能脱离现有的框架,对现有的入侵最小,其他的项目直接复用。

设计

  1. 打包生成的目录生成相应的项目指纹信息,也就是表示,可以是版本号、时间戳、哈希值等等;

  2. 路由钩子触发检测当前版本或者资源是否最新状态,来处理相应的逻辑,流程图如下

    tips:上面流程有点改动,改成点击菜单触发,这个在生产环境上大量测试上的改动。

实现

  1. 编写rollup(vite)插件

  2. vite打包改造,下面可以根据项目需要是否考虑加入,viite本身的打包模式,文件发生变动,打出来的文件名hash 会发生变化,未改动的文件还是之前的文件名格式

    tips: 上面为了好看,当然也可以不改,默认输出的就是带hash的js文件;

  3. 路由钩子处理 菜单上点击菜单处理

tips: 为啥没有放到钩子里面处理,是因为点击菜单会有请求资源直接报错啦,不会走钩子,所以无法触发更新的接口,当然可以放到离开的钩子上处理,目前用的保守做法,点击前置触发。

  1. 服务器Nginx上配置,红色部分是为了重载index.html禁止缓存这个html信息

通过 nginx ,禁用缓存:

bash 复制代码
# nginx.conf
location / {
  root html;root /Volumes/wanglaibin/work/vite-project/dist
  index index.html index.htm;

  if ( $uri = '/index.html' ) { # disabled index.html cache
    add_header Cache-Control "no-cache, no-store, must-revalidate";
  }

  try_files $uri $uri/ /index.html;
}

直接通过 html meta 标签禁用缓存:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>

  <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
  <meta http-equiv="Pragma" content="no-cache" />
  <meta http-equiv="Expires" content="0" />

</head>
</html>

其他补充

浏览器放大缩小,tab页激活触发

javascript 复制代码
	document.addEventListener('visibilitychange', async () => {
		if (document.visibilityState === 'visible') {
			console.log('当前会话被激活')
			await versionCheck()
			console.log('当前会话被激活-end')
		}
	})

浏览器聚焦触发

javascript 复制代码
  window.addEventListener('focus', async() => {
		console.log('当前会话成为焦点')
		await versionCheck()
		console.log('当前会话成为焦点-end')
  })

浏览器js资源加载失败

javascript 复制代码
	window.addEventListener('error', async (err) => {
		const errTagName = (err?.target as any)?.tagName
		if (errTagName === 'SCRIPT'){
			console.log('js 资源加载失败')
			await versionCheck()
			console.log('js 资源加载失败-end')
		}
	},
	true)

写在最后的话

其实具体到项目场景更为复杂,所以我们都是从问题入手、排查、方案等处理方式,不同的项目不同的处理方式,当然目前的对于当前来说更好的!当然可能过几个月就不一定啦!

抛出一个问题

其他我们平台还有比较棘手,目前已经处理,在测试过程中。我可以跟你们描述下问题就是可以一个浏览器多个tab可以登陆不同的账号,也可以登陆相同的账号,不同的账号不同的token,相同的账号也是不同的token 但是这些token写到session里面,页面内部也可以新开tab,内部新开的tab是相同的token,系统也要有一个token续期的功能,系统内部新开的tab 保证token同步不能失效,系统内部两个token ,一个接口token,一个刷新token,要用刷新token在失效前换取新的token之后同步到系统内部新开的tab中,但是但不能影响其他的账号登陆以及相同账号登陆的token。
或许为啥这样设计,没办法历史原因,现在就是后端不动,前端做token续期。

相关推荐
即将头秃的程序媛6 分钟前
vue 项目实现阻止浏览器记住密码
前端·javascript·vue.js
Williamoses7 分钟前
elementui table滚动分页加载
前端·vue.js·elementui
时光匆匆岁月荏苒,转眼我们已不是当年8 分钟前
【VUE小型网站开发】优化通用配置 二
前端·javascript·vue.js
Serenity_Qin9 分钟前
vue3 + ts 使用 el-tree
前端·vue.js·typescript·vue3·element-plus
fury_1231 小时前
当大的div中有六个小的div,上面三个下面三个,当外层div高变大的时候我希望里面的小的div的高也变大
前端·javascript·html
大鸡腿最好吃1 小时前
为啥react要用jsx
前端·javascript·react.js
小黄编程快乐屋1 小时前
前端小练习——大雪纷飞(JS没有上限!!!)
开发语言·前端·javascript
程序猿阿伟1 小时前
《平衡之策:C++应对人工智能不平衡训练数据的数据增强方法》
前端·javascript·c++
STUPID MAN1 小时前
vue3使用后端传递的文件流进行文件预览
前端·javascript·vue.js·文件预览
-代号95272 小时前
【React】二、状态变量useState
前端·javascript·react.js