暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

微保小程序的前端版本兼容方案

微保技术 2020-05-22
742

作者:seaslu 鲁海

编辑:edwinzeng 曾鑫鹏

1

背景

虽然微信小程序(以下简称小程序)的开发同普通web开发相比有很大的相似性,但由于小程序独特的更新机制——在24小时以内有可能出现小程序新旧版本共存的情况,这让原本在一般web开发流程中无需过多关注的版本兼容变得尤为重要。这跟APP开发有些相似,都有会出现多版本共存的情况,同时由于小程序自身的设计原因又跟APP的版本兼容解决方案有些不同。


2

方案

总结微保在小程序版本兼容方面的经验,我们主要在解决两个问题。


问题1:业务接口不兼容多版本小程序

这个问题比较常见,一般有三种方式来规避问题。

第一种是规范和测试手段。一方面要求业务接口协议字段只增加不删改,以此保证向下兼容,如此每个接口只需一个最新版本即可。另一方面通过单元测试或正式测试流程增加接口兼容性验证,防止开发人员不小心犯错。这种方式绝大部分时候能正常运作,但总不免偶尔因为项目赶工而导致有开发人员忘记兼容性且测试流程未能完整验证兼容性从而泄露bug。


第二种是为不同版本的协议生成不同接口,在请求的URL中也加入版本号以示区分。

/user/loginv1
/user/loginv2

这是目前最常用的方式。虽然一定程度上增加了维护成本(可通过自动化工具改善),但对开发人员要求较低,研发质量更加稳定。旧的接口监控没有流量以后也可以及时删除,无需长期存在。


第三种则是为不同版本生成不同的微服务。接口URL可以不变,版本信息附带在请求参数中,作为默认值自动填入而无需开发人员手动填写。路由组件根据版本请求不同版本的服务,如此则前后端的业务开发无需再关注接口版本,发布部署的时候发布工具根据git.tag自动发布到不同的服务即可:



这种方式是相对一劳永逸的解决方法,但必须要有发布工具的辅助,否则运维成本过高而不可行。


问题2:消息推送的小程序卡片打开旧版本的页面

对于小程序,问题2会更直接的给用户带来错误的交互体验。在官方提供API以前,几乎只能靠不断删除小程序来更新。



而目前官方提供的重启并更新API(UpdateManager.applyUpdate)功能也很简陋:

  1. 不支持自定义重启参数

  2. 不保留重启前的路由栈,即无法恢复到最后的页面

  3. 重启后也并非从小程序配置的启动页启动(LaunchPage),而是重启前启动小程序的第一个页面(并非矛盾,因为在一些场景下,比如消息推送,小程序码等,交互经常是直接启动小程序进入目标业务页,不需要再经过启动页)



同时,根据官方对路由栈的描述,我们也无法强行构造路由栈,否则会给整个小程序带来一些未知的风险,得不偿失:




所以为了尽可能的不牺牲用户体验,只能退而求其次,至少还原到重启前的最后一个页面:



为了解决上述问题,小程序中我们提供了一种强制更新机制。它主要分为三个部分:配置信息,前端组件与路由处理



① 配置信息

在迭代频繁的版本发布中,并不是所有页面都需要更新,全局的版本更新提示也会频繁的骚扰用户,所以按需更新提示是必然。



  • 更新路径:以唯一的页面路径为key,作为按需执行更新逻辑的标识

  • 最低版本:小程序加载到的配置版本大于当前版本即表示需要更新(拉取最近10次版本的发布git.tag为内容,新增的更新路径默认选择最新的tag版本)

  • 强制更新:顾名思义。如果选择是,则还需要在页面中引入组件,否则配置无效

  • 自动重启:无需重启确认对话框,在新版下载完毕后自动重启


② 前端组件 <update />

为什么需要单独的组件? 有两个原因:

(1) 官方API,从UpdateManager.onCheckForUpdate(有新版本更新)到UpdateManager.onUpdateReady(新版本下载完毕,可重启)有一定的时间差的,这会导致在新版本下载期间,会被用户看到不兼容页面的样式及业务逻辑错误,所以我们需要loading遮罩层盖在最上层。


(2) 官方示例中的模态对话框wx.showModal在不同系统版本上的表现不一致,也不能作为阻塞式的提示手段



因此使用强制更新的页面需要手动引入一个组件,作为新版下载期间的loading遮罩层和提示对话框:


更新组件的出现条件则必须满足:

1)配置信息中的条件都满足

2)UpdateManager.onCheckForUpdate 回调参数res.hasUpdate为true,有新版本更新,弹出loading遮罩层

3)UpdateManager.onUpdateReady 回调执行,新版本下载完毕,可调用UpdateManager.applyUpdate重启。


根据配置是否需要自动重启,在UpdateManager.onUpdateReady回调中直接重启或者弹出确认对话框。并在重启前把当前页面的路径,参数以及当前时间戳存放到本地缓存storage中,以备在重启后恢复当前页面使用。

③ 路由处理


最后一部分只需要拦截路由(或者在生命周期onLoad中),优先判断storage中是否有满足我们条件的页面信息,跳转即可。


其中设置了10秒的有效期,即从点击重启按钮到重启结束的时间要小于10秒,则认为storage中的信息是有效的。目的是最后的容错处理,避免没有成功清除掉storage的历史信息,而导致整个路由错误。

3

小结

强制的更新势必会给用户带来困扰和体验受损。它应该是在解决版本兼容问题时,最后才考虑的一种方式,而不是完全依赖于此而忽略必要的兼容性设计。


 



文章转载自微保技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论