UU跑腿前端中台方案

简介

前端中台方案是针对在 vue 单页面应用中切换到缓存的页面时卡顿问题的解决方案。原理是用多个自定义组件同时存在于文档中代替单个router-view组件展示页面,同时使用iframe标签解决性能问题。
解决的根本问题

切换页面卡顿的问题

顺带解决的问题:

1.多个项目业务由于业务重合引起的重复开发问题;
2. 项目太大启动、打包慢;
3. 发版时原项目资源丢失,导致打开新页面无反应问题;
4. 每次发版都需要全量打包;
5. 技术栈一旦选定无法更改。

背景

UU跑腿后台项目用的是vue脚手架,和传统的后台项目一样,页面顶部会有 tag 标签用来记录打开过的页面,点击这些标签会显示对应页面并恢复切换之前状态(我在客服轮岗时感觉这个功能用处很大,可以提高效率,一定不能砍)。原来的项目是通过 keep-alive 标签实现的,原理是 keep-alive 标签保存了对应 router-view 的虚拟dom,将需要展示的虚拟dom拿出来渲染到页面上,但是使用这种方式有一个问题:在切换页面时会出现卡顿的情况,尤其在回显订单列表等大型页面时,从点击tag到页面显示完成甚至会有500毫秒左右的延时,非常影响用户体验。经过调研,发现 element-admin、华为云等一些管理后台等这些后台要么没 tag 标签,要么也是用的 keep-alive 。后来经过沟通确认他们想要总代后台(老后台,用的还是前后端不分离的技术)这样的效果,我去试了,有记录页面数据的功能而且切换很丝滑,所以我就去查看它的实现原理,发现这个项目分为2部分:外层有左侧导航、一级头部和页面标签,内部通过 iframe 标签打开业务页面,然后通过控制 iframe 的显示与隐藏实现页面切换的效果,总之一句话:所有业务页面都 body 中,但是只显示对应链接的业务页面。基于 vue 脚手架,要想将所有业务页面都放在body里,可以通过命名视图来实现,即一个业务组件对应一个 具名router-view ,这些具名router-view提前注册到页面中,根据路由的变化将其添加到body中,再根据页面缓存策略卸载,但是考虑到一个子页面会有很多元素,而且缓存的页面如果都是真实的 dom 会出现更严重的性能问题,最后就舍弃了 router-view 组件,封装更灵活的自定义组件,并在自定义组件中使用 iframe 标签承载页面,每个缓存的页面对应一个自定义组件,切换路由时改变组件的显示/隐藏状态即可。

实现

要实现这个方案有两方面的工作:
现有后台:

  1. 自定义组件的封装,可根据传的参数得到iframe需要打开的链接并添加token信息用于打通登录,子页面加载 loading 状态的控制,和子页面通信,主要是状态通信:页面加载完成、token验证不通过、更新token、token失效、跳转页面等。
  2. 页面结构调整,将 router-view 标签更换为自定义组件(也可以不删除 router-view 组件,这样即可以通过 router-view 打开后台项目自身页面,又可以打开其他项目提供的页面(以下称中台项目),这样功能更加完善,而且可以让老项目过渡更平滑)用以打开中台项目提供的页面
  3. 路由信息处理,用来实现页面缓存的功能
  4. 开发自定义指令用来根据当前路由信息判断当前组件的显示状态,并告知中台项目页面,用以代替原本的 activated/deactivated 钩子

前端中台:

  1. 页面基础结构搭建,根组件中只有一个 router-view 即可,添加无资源、权限获取中等状态页面
  2. 权限处理。
  3. 路由跳转函数重写:在当前页面中通过 $router.push 打开其他页面时,实际逻辑为通过 postmessage 告知父页面,通过父页面打开,这样做是为了保证 tag 标签的记录页面功能
  4. activated/deactivated 钩子函数中的逻辑,通过接收父页面的通信而触发

过程

  1. 首先需要准备中台项目。 我选用的是最新版的 vue 脚手架(原后台项目为 vue-cli 2.0 + iview2)。由于重新开发成本太高,就需要拷贝后台中的页面代码到新项目中,为了让老代码在新项目正常运行就需要在新项目中添加需要使用的自定义配置,如:组件库自定义样式、公共方法、自定义全局组件等。页面权限及其他配置信息考虑复用当前后台的逻辑:通过 token 获取并保存在 sessionStorage 中,即中台页面没有自己的权限,使用的是对应后台的权限,这部分逻辑需要依赖 token,而且情况较多,后续再处理。
  2. 加下来就要处理引用问题。这一步主要实现根据不同路由信息显示不同的组件:后台本身的子页面通过 router-view 组件承载,中台的页面需要通过自定义组件承载。现在已经有了 router-view 组件,所以先建一个占位组件用来表示自定义组件。考虑到中台项目不止一个,所以需要在路由信息里标识以添加区分中台页面和后台页面,而且还能通过标识确定调用哪个中台,所以就在 router 配置文件中,在 meta 中添加 mgSite 字段,调用后台页面则赋值 false,需要调用中台资源则赋值对应的中台子目录,如 i2。具体的处理逻辑为:给 keep-alive 中的 router-view 组件添加 v-if 指令,如果当前页面的路由信息的 meta.mgSite 为假值则表示需要显示 router-view 组件,给 v-if 赋值为真,让自身页面正常显示,而自定义组件隐藏;当 meta.mgSite 值为字符串时,给 router-view 组件的 v-if 指令赋值为假,然后让自定义组件展示。接下来编写自定义组件。
  3. 编写自定义组件。这个组件的功能有:
    1. 处理需要打开页面的链接;
    2. 收集子页面返回的信息,并处理;
    3. 添加页面加载状态,优化用户体验
      对于需求1由于中台使用的是后台的权限,而权限管理是根据 router.path 配置的,所以在这个组件中只需要获取后台的链接,并处理成对应站点的链接并拼接 token 信息用来获取权限及验证 token,还需要添加后台对应的标识用于区分不同后台特有的功能。在这里就用到了之前设置的 meta.mgSite,用法就是将 meta.mgSite 信息添加到链接中以确定中台站点下对应的子目录。
      需求2为通信问题,根据项目考虑到子页面可能会有页面加载完成、token失效、页面跳转等状态需要处理,所以需要有通信逻辑,我这里使用的是 postmessage+addEventListener 处理,这里需要注意的是,子页面在传递信息的时候需要添加当前页面的 router.path 以便处理对应组件。组件编写完成后,切换到中台子页面时就需要打开中台页面了。
  4. 中台的权限处理。进入中台项目时先获取链接中的 token 信息并与 sessionStorage 中的比对:1) token 一致则说明当前登录状态正常,直接渲染页面;2)token 不一致:可能出现的场景为权限变更后的重新登录或更换了登录账号所以需要清除 sessionStorage 中的信息,重新获取并保存。3) sessionStorage 中无信息,则跳转到登录页面,并执行权限获取操作,完成后回到需要展示的页面,如果 token 无效则通知父页面,由父页面退出登录或者给出带有新 token 的链接。
  5. 中台跳转业面。这个方案的原则就是每个页面都有一个标签,所以 iframe 标签内的站点不能进行跳转操作,只要有打开新页面的需求只能由后台处理,所以需要对中台的跳转进行拦截,重写 $router.push 方法,将需要跳转到的路由信息传递给父页面,由父页面执行跳转操作,这样也保证了子页面和父页面的链接统一。到此这个方案的主流程已经通了。
  6. 页面缓存实现。页面跳转时收集中台页面的路由信息并处理,处理逻辑为将搜集到的路由与之前搜集的路由信息数列匹配,如果之前没有保存则判断为新页面,执行插入或替换操作(缓存的页面数量已到最大值)并处理代表最近使用顺序的参数,如果当前数组里则只需处理代表最近使用顺序的参数,这样就保证了切换页面后恢复原先状态的功能,使用 v-for 指令通过自定义组件将中台页面映射到后台中。
  7. 在完成主要功能时会引起有一个问题:vue 框架中 keep-alive 组件提供 activated/deactivated 钩子函数,用来处理缓存过组件回显和需要缓存的组件隐藏需求,现在的这个方案中由于页面都保存在 body 中,回显和隐藏时没办法再触发生命钩子,所以会有一些功能无法满足,如某个跑男详情页面缓存后,通过其他页面如订单列表处理了跑男信息后,再回到跑男详情时显示还是原先的数据,不能做到实时更新跑男信息,所以就需要通过 postmessage 告诉中台当前页面的状态,而中台页面中原本通过 activated/deactivated 触发的方法需要通过 addEventListener 触发。

优化

功能完成后就需要针对当前模式进行优化,优化内容分为常规的项目优化和本方案定制优化。
常规优化主要针对中台项目:

  1. 缓存优化:使用协商缓存,服务器这边默认是强缓存,会出现发版后页面打不开的情况
  2. 使用 vue 脚手架的按需加载功能
  3. 依赖的工具库如:vue、vue-router、axios、iview、lodash等资源通过 cdn 的方式引入
  4. 将一个大的代码包分成若干小的代码包,提高 tcp 连接的利用率

本方案定制优化:

  1. 中台项目拆分优化:使用地图的页面放在一个项目里、使用图表的放在另一个项目里,其他的页面可以按业务拆分,这样可以避免加载无效资源
  2. 渲染优化:一开始用的是 display 属性控制显示与隐藏的,经过实际使用发现还是有卡顿的情况,后来就使用 position + visibility + zIndex,变重排为合成,大大提高了渲染效率
  3. 安全性加强:前端中台环境判断,正式环境下的前端中台项目只能在 iframe 中打开;设计一套通信时的数据加密逻辑用来确保通信安全
  4. 页面缓存逻辑优化:由原来的 LRU 策略修改为 ALRFU,提高缓存页面的命中率。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值