李永亮 盛大游戏游麦团队前端负责人
大家好!
我来自盛大游戏游麦团队前端负责人-李永亮,很荣幸这次被选中,与大家分享下weex在我们实践中遇到的问题。
今天我的议题从五个大方面来说,从技术选型选定Weex,到在产品中小试牛刀,再到后来大规模的页面实践,再着遇到性能上的问题怎么去优化,最后是踩坑填坑的历程。
一、技术选型
我们为什么要选Weex方案呢?其实在2017年年初的时候,我们CTO期许各技术团队要高效开发、节省成本,产品快速迭代。所以在这种倡导下,各团队开始研究RN、Weex。
我们游麦团队为什么选择了Weex呢?
(一)首先是高效交付
1、它支持三端(iOS/Android/H5);
2、运用了Web的技术,像CSS、JS等,我们团队中主要的前端框架是Vue;
3、Vue用起来非常简单,如果Android或者iOS同学想学习Weex的技术,也是十分容易的;
4、我们是在现有App中接入Weex页面的,有新的产品页面开发,还有原有Native页面转化成Weex的过程。很多原生功能做得非常好,我们是希望充分利用原生的能力,Weex的可扩展性,正好能够在这上面发挥作用。
(二)它的性能上来说非常优异的,Weex最终打包的bundle文件体积非常小,不像RN那样依赖过多冗余代码;它的渲染速度也快;Weex对资源利用还是做了很多努力,这方面确实值得信赖。
(三)除了阿里集团内部在使用这些产品,下面这些数据,阿里的同学统计了一些数据,加上我在知乎上搜集了一些信息,得到了这些数据。
二、小试牛刀
我们公司有两个团队在同时尝试接入Weex。信息化团队在做公司内部App的食客在线频道页,这个weex页可以直观看到内部食堂的就餐情况,它是通过原生控制来横屏展现的。
右边是游麦电商平台的系统消息页,是一个典型的列表页。大家会看到,最开始是从原生页面跳到此列表,点击列表项就跳转到原生页。
在这两个接入页面中遇到一些问题,和大家分享一下。
(一)最开始用的Weex版本是0.7.0,我们在两部手机上,小米5和三星中,不同的SDK版本下页面会有不同的展现。红色的区域是有问题的。我们发现在SDK0.10.0这个版本上,list是没有问题的。所以有可能的话,尽量升级为高版本的SDK。我们目前升级到的是0.12.0,比较稳定(不过建议大家再往更高版本升级)。
(二)那个列表页需要带有用户登录态,Weex虽然不支持Cookie,但是可以借用原生的Cookie能力,调用原生的Cookie做到用户登录态的介入。还有一种方案,我们还有团队采用在接口中传递Ticket票据获取用户登录态的方式这是原生中封装的一个自定义module方法,每个请求都会带上Cookie;也可以Native拦截接口请求并添加Cookie信息
(三)刚才的列表页跳到原生页需要传递参数,我们要把用户的一些订单信息传过去,这时Native可定义一系列的跳转协议,协议的前缀比如sdggmm://,Native会统一做url解析并跳转目标页,原生同学要把所有可能跳转的页面全部提前写进去。
(四)刚开始按照官方的文档,采用了.we的版本,后来官方推荐使用.vue版本,我们使用了一些工具进行转换,之后稍作手工的调整就切到.vue版本。
三、大规模应用Weex
我们在代练业务中差不多21个页面用到Weex,在公司会议系统中有7个页面用到Weex。
从展现上来说,体验令人激动。不过在做之前,我们先考虑了很多问题。
从五方面去考虑:
我们比较习惯做单页面应用,但Weex应用也采用单页面方式合适吗?其实Weex支持单页,也支持多页,这两种方式看你怎么选
第二个问题,Weex页面之间的跳转会存在什么问题
第三,Weex页面的跳转会带一些参数,或者通信问题该怎么解决
第四,样式的复用
最后是怎么充分利用Native的一些能力。
(一)有一个同学也问到这个问题:用单页还是多页?我开始是以单页的方式做的,用路由做确实有一些好处:可以避免重复加载一些资源、自定义专场效果、数据可以共享。
实际上我发现打开Weex页面,经常出现APPCrash情况。再加上多人合作时,协作比较差。还有APP进到Weex有多个入口,还要做一些特殊的处理。还有Vue全家桶这个东西对团队成员来说有点学习成本的.
所以说基于考量,最后我们就选定了多页的开发方式。每一个页面就是一个bundle,如果拆分得足够好其实很小。那种Crash的情况也会减少,专场效果和原生保持一致等等.
(二)页面跳转会存在一些问题,我们刚接入的时候本来希望是正常的,实际会有右边这种情况。这个本身也不是Weex的问题,而是原生页面默认设置的navigationController问题,最后我们采取的方案是我们自定义一个Push方法去覆盖SDK中的Push方法,这样所有Weex打开页面都会隐藏头部导航,大家在接入Weex时注意下这一点。
(三)数据通信问题,是很多团队比较关心的。从Native跳到Weex要传数据,Weex跳到native也要传给原生数据,WeexA页面跳到B页面。还有WeexA页面跳到B页面,再pop回到A页面。还有最下面的WeexA页面跳到原生页面,再回到WeexA页,这些应用场景下数据的传递,我们经过了一些尝试,有一些参考方案。
1、Native跳到Weex,刚才列表页就是一个典型的例子。可以用原生去封装数据变量,实例变量,把order_id等数据包进去。
2、Native向Weex主动传递数据,相当于推送。右上角的消息数量,这是主动推送数据给Weex页的场景。我们会怎么做呢?其实就是订阅原生的事件,如果原生推送到了以后,监听这个事件的Weex页面就可拿到数据,是通过这种方式解决推送。
3、Weex向原生传数据,就是像前面说的通过url拼接,原生抓到url并对url进行处理。
4、WeexA页面传到WeexB页面,这个大家都经常处理。我们的JS全部是通过预加载本地,是在APP本地中无法运用到url解析方式,所以用到了storage方式,在A页面set数据,在B页面get数据,拿到时回调中做一下remove,否则可能会导致后面操作受影响。
还有一种解决方式:viewappear与viewdisappear。
5、在A页面跳到B页面,然后B页面pop并回传一些数据给A页面的情况。在原生中,到B页面之后是一个view栈压在上一层,再回传回来的话A页面像休眠一样。这时候怎么把数据传回来?看一个场景吧!
我在左边这个区域选了区服,弹出右边的Weex界面。选中一个区服数据,回传数据到左边的Weex页面。
我们是怎么做的?.we这个版本有BroadcastChannel对象,是可以解决的。但是vue版本不支持(注意:现在新的SDK版本已支持)当时我们不知道怎么办,后来讨论了一下,发现还是可以用fireGlobalEventCallback做一个封装,封装一个sendEvent方法.
它的过程是在WeexA页面跳到B页面时,B页面做了操作以后,A页面其实在监听B页面的事件。你在B页面回传时会发送一个事件,A事件监听到这个事件,A页面就在回调中拿到了想要的数据。
6、还有一种场景,从WeexA页面跳到Native的页面,为什么跳到native的页面呢?因为有些Native页面是可复用的,它的功能很独立。比如一个短信验证原生页面、评价页,它非常通用,这类页面没有必要做二次开发,可直接调用;调用完以后,它会跳到另外一个Weex页面。我们是一个游戏虚拟电商的平台,会有支付的流程,我们会封装一个自定义的module。
比如支付,下单页面支付完之后,成功跳到支付成功页面。在这样的场景中调用了Native钱包支付页,我们会调用fireEvent,弹起原生支付钱包流程,支付完以后就进行回调。
我不认为我们的做法是最佳实践,希望Weex团队给出一些最佳实践和通用方案出来。其实这个问题不仅仅是我,很多团队都会遇到通信这方面的问题,希望官方有些反馈。
(四)样式怎么做复用,多亏了CSS-loader,我们可以形成组件化的样式文件。因为样式在Weex中不能嵌套,SASS的很多优点不能得到很好的发挥,所以我们放弃了SASS工具。
(五)接下来非常重要的一个内容,就是充分利用原生的能力。很多Weex页面,比如图片上传或者分享组件,然后图片放大缩小的全屏预览,等等一些原生的功能,它已经封装得非常好。而且像调用支付SDK这种,Weex还没有这方面的能力,我们可直接自定义一个module使用。其实Weex的优势就是可扩展性,有一些想象力在。
四、性能优化实践
说到性能优化,我们主要是对两块进行了优化。其实网络加载这个问题也不是关键,因为我们bundle资源都是APP打开后预加载的(Weex页面一般在三级页面)。预加载的bundle资源是经过压缩,图片也经过压缩,然后本地访问非常快。
其次是注意scoller和list的使用。长列表一定要做懒加载,还要划分好cell颗粒度,嵌套不要太深。像我之前做单页,我都怀疑当时做单页是嵌套太深了,所以导致App偶尔出现Crush。嵌套一定要扁平一些,这时候就考验前端工程师的功底了。
性能优化这方面上午阿里同学已经讲过,我们首选list,还有未来的list性能会更好,我们好好期待吧!平时还要注意划分好Vue组件的颗粒度。
五、踩坑填坑
(一)Dialog点透问题。点透的问题,这个弹出框和Mask是平级标签,但点击中间弹出区域莫名会触发Mask层的关闭事件,当时感觉有点懵了。后来怎么解决呢,就是在弹出层加一个阻止冒泡事件。
(二)这是一个图片放大的东西,会有轮播、放大,全屏的展现。后端反馈的数据没有带宽高信息的,这种情况下对于Weex做上下居中,放大缩小,做轮播,刚开始做这个图片,在不知道宽高情况下做上下居中有一点困难。因为image标签一定要规定宽高才好,当时直接利用自定义原生控件封装好,两行代码搞定,我觉得很方便省事。
其实我是希望它返回url带一些宽高信息,这样就可以根据宽高信息来定位图片。
原文发布时间为:2018-01-29
本文作者:李永亮
本文来自云栖社区合作伙伴“淘宝技术”,了解相关信息可以关注“淘宝技术”微信公众号