Weex实战分享|企鹅电竞Weex实践和性能优化

简介:

8a3f9d6186b146914bd3c1afc2f3dddb9e36d96c

渠宏伟 企鹅电竞前端团队Leader

H5页面存在的问题

H5页面对比终端的不足,第一,加载慢;第二,交互差。

0a9e60ccf1970b5eb91a2617ac8b9be6d65be451

加载耗时比较长,因为它受限于Webview,Webview在Android上启动就比较慢,另外页面资源加载慢。我们很多业务页面都是用H5做的,长列表滚动和侧滑操作存在明显的卡顿,经过持续优化也很难和原生界面媲美。

H5极速加载方案 ——VasSonic

加载慢的问题,我们实现了H5极速加载方案 —— VasSonic,加载速度实现秒开,在手机QQ上广泛应用。

  • WebView和页面并行加载
  • 资源离线预推
  • 页面局部刷新
  • 动态缓存
4e2a734651bf1db89274c608990478bf3a10e5ff

H5页面首屏实现秒开 (https://github.com/Tencent/VasSonic)

Weex实践和收益

为什么选择Weex

  • 企鹅电竞正在快速发展中,我们需要一套兼顾性能与动态性的技术方案来支撑企鹅电竞产品日益丰满的业务需求,weex是一个不错的选择。
  • weex选择了vue作为上层框架,代码编写体验和使用vue差不多。企鹅电竞前端团队的许多项目之前也选择了vue作为开发框架,小伙伴们可以快速上手。
  • facebook的专利许可证风波让开发者们人心慌慌,不敢再使用他家的React Native。 weex借鉴了React Native的思想,是一种不错的RN替代方案。

db43cc7fcc4d5ffb2a001fa8bf5806520a9e1804

我们选择了Weex作为原生渲染方案,它的主要特点:

  • 前端页面原生渲染,增强前端页面体验
  • 一次开发支持三端(Android、iOS、H5)运行,提高开发效率

在企鹅电竞业务当中大量使用了Weex,如果想体验一下可以下载我们的APP,可能你都看不出来哪部分是原生做的,哪部分是Weex做的,它是一个融合的方案。

d4bede37a5cdd161a5e1873b1ac192d7cc5f4453

获得收益

e1faf2c9f2e7be98f16b7ab9552eb602aa798fa1


  • 内存降低 45%,帧率提高 15.7%;打开耗时下降 44.9%
  • 开发效率比终端提升 40%,有效释放终端开发人力
  • 页面更新不依赖版本发布,特性发布效率提升
构建流程改造

我们接入时首先做了一个构建流程的改造。这是Weex官方构建图,用一个公共APP进行webpack打包。我们的应用比较复杂,往往在H5上有一些特殊的逻辑,或者在原生上有一些特殊的逻辑,如果是统一写在app.js里,就会造成两边打出的js有冗余。

8373426b7912aea52239cde9d5aa021450bbe857

我们就做了一下改造,其实改了页面的开发方式。除了app.js之外,又分成两个入口,一个是对web的,一个是对Weex的。

21038746726c3b03c0ea3bd1a4f135f23988a538

分入口再引用相同的app.js,可以让web版本和weex版本保持相同逻辑,也可以独立扩展,互不影响。

接头暗号

头部的{"framework":"Vue"}告诉解析器用Vue的语法解析JSBundle。如果删除了这行注释,将会白屏。

0191bee8ab8523c9c20fc01843f91a856ff5fb06

Uglify压缩会删除注释,导致”接头暗号”被删除。压缩必须放在插入framework之前

722d248ec8d9bc881ffb23b2b120faf38dc24008

调用终端接口

我们的APP接入Weex之前是很成熟的APP,有大量jsapi,如果全部改造成module工作量太大,做法是统一做一个module转发,直接传过来,由module统一解析转发到对应的逻辑,底层jsapi的解析和逻辑保持不变。这样的话,我们的Weex页面直接就集成了原来所有Webview的jsapi能力,是一个通用的。并且以后开发新的接口时,只需要开发一份。

84f77b8e5b6eccdfadd5adcc65ea679371702ecb
支持cookie

H5中我们使用document.cookie可以获取浏览器的cookie信息。

在weex中如何实现?我们利用weex提供的扩展module的能力,在终端中扩展一个获取cookie的方法。

54fd4e9ba68a6f039e2b54f7f0c4fbe6c32e4d22

接口请求支持cookie

  • iOS基于UI     webview共享cookie。iOS天然支持请求带上cookie
  • android需要终端支持,使用cookieManager管理cookie信息,拦截请求自动添加上cookie
ce3cab42692d2be4bddb402d04453c333e1e3b16
支持userAgent

H5页面经常使用UA判断APP环境和版本号,为了兼容H5的逻辑,我们在Weex中支持了userAgent,在weex.config.env添加userAgent属性。 需要注意的是,从weex实例中获取的userAgent是静态的。一旦weex实例创建就固定下来,终端修改UA也不会跟着变化.

11b9c5257e0d4865a5e2551877a606df7f22ce3e

如何实现1px

weex px问题是一个坑,定义成了自动缩放单位,颠覆了前端对px的理解。我个人认为,微信小程序的方案是对的,定义一个新的单位rpx实现自动缩放,不影响原来px的实现。

在我们的业务场景中需要使用weex实现titlebar。在宽屏手机titlebar会被缩放,跟终端的titlebar体验不一致。通过动态计算对应的px,重新设置样式,实现和终端一致的体验。

7bb14e1227e4b76af49e1d91f007ac3a94faf16c

e5e3bb9ebae268165d5ad53676fa3e94a75a737a

横屏适配

510b728a0a283c578bd31692de0242d2521a09b2

设备宽度deviceWidth是固定的,横屏状态下设备宽度为手机长度,并不是我们的view宽度。看上面的公式,我们可以前端修改viewport宽度750。

0b73248e4faa6cbfe8a9b0b61c834151ef66c327

适配后就如下图所示效果。注意,meta.setViewport执行时机比较晚,如果希望一开始得到准确的渲染宽度,需要终端同学帮忙weex初始化时设置viewport。

:class 语法限制

a9c4adc244ec8f8cc2aa677277097c523b122a66

点击态

项目比较常见的点击态多半是透明度的变化,如按钮、列表、链接等,css的做法是添加伪类 (:active),weex中也同样支持,但是weex需要在原样式中添加 opacity:1,否则点击后回不到初始状态;

828bbcc0a29865f12200ed32d28914a9bc000724

此外,:active使用时,background-image在ios下会失效。

文本截断

文本从限制1行到不限制可以用lines:0

f69116173a7eb942af31b74c466866cd7ab5475e

圆角抖动问题

圆角按钮会先显示直角再变成圆角,出现明显的抖动,问题存在于android下 weex sdk

1358a83471155c2428b79c0cb76e773d106ece6d

发现weex sdk代码中做了64ms延时造成的,配合在新版本weex sdk解决了这个问题

a80cce3a8a27b2603d39d5f7b672d6b8dbed53e1

终端crash问题

Android

  • OOM
  • PaintDrawable在API 21下偶现渲染crash
  • Bitmap回收后继续使用导致crash
  • instance被销毁后调用Toast的NPE问题
  • WXThread.secure反射调用异常

iOS

  • 未显示禁用estimatedRowHeight导致
  • tableview在更新数据源时偶现crash
  • 布局时node->get_child返回空指针导致crash
  • text component渲染和测量高度时偶现crash

Android接入Weex crash率 0.13% -> 1.01%,我们遇到的这些crash问题在企鹅电竞已经解决。

自动化测试方案

weex sdk生成的终端view中的id是自动生成的,自动化测试系统无法识别。

我们借助无障碍化ariaLabel属性作为原生view自动化测试标签。

18258fe6b4ff4c62e9d8a883471ed9e14fda8a62

性能优化

数据缓存优化

1、使用storage缓存接口请求数据

2、优先使用本地缓存数据,同步请求更新缓存数据和页面

380a8ea49fa6fa0dbd735fbd9cc619898ca3379e

jsbundle预缓存优化

1、在现有的 weex 页面配置文件的基础上增加一个字段 preload,当此字段值为1时候,对jsbundle文件进行预缓存。

d84cc0db262cd64127f732dd9c6ffd11ce04956e

2、提供js api : biz/preload 提供给前端进行对下一个页面的预加载。biz/clearProload 用于前端对于既有缓存内容的清空.

3、对于缓存内容,使用LRU的算法进行管理,控制缓存总大小为20M。

4、对于使用缓存的内容,终端在ua上添加一个字段 PRELOAD/1 ; 1表示是预缓存内容, 0表示不是。

d51328741a7ef1711bf78c872a9946949a802581
耗时打点统计

我们一直关注页面加载的性能,问题到底出在哪儿,是终端耗时,网络耗时,还是页面逻辑耗时,我们在Weex页面上打了一系列点,Webview时期也打了很多点统计这些数据。终端、前端两份上报,目的是相互对账。

  • 拦截请求开始、请求完成、RenderFinish计算网络耗时(请求结束 - 请求开始)、终端渲染耗时(RenderFinish - 请求结束)
  • 终端通过js api提供前端创建instnace时间点
  • 终端、前端两份上报,相互校验数据,生成性能报表,快速定位性能问题产生的阶段
30c01fcbd466a738932833b134ee688b0e667b85
终端接口调用耗时优化

1、Android 升级weex 0.16版本module接口调用耗时大幅减少。

终端接口耗时优化,这是一个比较现实的问题。最早接Weex时接的是0.12版本,当时调用一次module接口50-60毫秒,后来升级0.16,这个问题就解决了,Weex团队持续做优化,这是一件好事情。

d574ed6563ced9d26a42f19d12bf4105d972782c

2、减少启动页面时并发调用module接口。

现在接口单次调用2-3ms,但是并发请求性能很低,需要60ms以上,这个对前端页面是很大的损伤,希望这一块能够持续优化解决这个问题。

3、Android 调用时多次反射获取类名导致Dom渲染耗时过长。

Weex里的小bug,调用时多次反射获取类名,导致Dom渲染耗时过长。其实一次调用时间并不长1ms,需要调一百多次,就造成很大的耗时了。

f3e20d196d3b08afc03e91fc53eef21d4f4e1613

Android Bitmap 内存优化

429cd02190795a96735254839af900e80b747e17

使用Fresco管线加载图片,加载后不持有图片引用。

问题:

  • 会将用户当前不展示的图片也加载到内存中,实际占用内存变多,OOM问题严重。
  • 引用不被持有会导致Bitmap被回收后仍然被使用(3.2 - 3.4版本top crash—SIGSEGV (SEGV_MAPERR))

优化: 仿照Fresco的DraweeController管理WXImageView的bitmap引用。 显示时加载,隐藏时解除引用等待回收。

OOM问题明显缓解,bitmap被回收的crash问题也得到解决。

GPU过度绘制优化

2ef7096ad18d6e6911d1e22a1f1e54ce75752333

GPU过度绘制是终端开发很关注的问题,通过优化层级,提升渲染性能。我们上了Weex后没关注这个问题,重构按照以前的开发方式,设置很多层和背景色,生成的Weex页面打开Android调试发现大面积是红的,过度绘制很严重。

优化方法:

  • 尽量不要设置背景色
  • 不要过度嵌套,结构尽量扁平化

e83cb1d0f6570d518801a85857cba079bdc4e3b4

Weex实践分享——内部影响力

66848c333d69579c5c2c26777b6bedad1fb69784

希望优化的问题
  • 横竖屏切换方案支持
  • 支持armabi-v7a的so包
  • 组件统一开源:例如 jscore内核、debugger、gcanvas
  • 更好的性能细分统计
  • 高效的终端和Weex共享动态数据方案
  • 更好的容错: iOS JS call Native时,参数传错会造成终端crash

 

原文发布时间为:2018-01-31

本文作者:渠宏伟

本文来自云栖社区合作伙伴“淘宝技术”,了解相关信息可以关注“淘宝技术”微信公众号



相关文章
|
移动开发 weex 双11
【双11背后的技术】Weex 双11会场大规模应用的秒开实战和稳定性保障
作者:鬼道  前言 Native 开发的诸多亮点中,流畅体验和系统调用是最多被提及的。流畅体验体现在页面滚动/动画的流畅性,背后是更好的内存管理和更接近原生的性能;同时又是 Web 的痛点:资源首次下载、长页面内存溢出和滚动性能、动画性能、传统 web 性能(如JS执行效率)。
4724 0
|
Web App开发 移动开发 weex
【阿里鬼道】Weex在双11会场的大规模应用:业务支撑、稳定性保障和秒开实战
前言 Native 开发的诸多亮点中,流畅体验和系统调用是最多被提及的。流畅体验体现在页面滚动/动画的流畅性,背后是更好的内存管理和更接近原生的性能;同时又是 Web 的痛点:资源首次下载、长页面内存溢出和滚动性能、动画性能、传统 web 性能(如JS执行效率)。Native 有丰富的系统调用能力
6298 1
|
移动开发 JSON JavaScript
weex开发 - VS Code解除格式警告
weex开发 - VS Code解除格式警告
71 0
weex开发 - VS Code解除格式警告
|
weex-ui 移动开发 JavaScript
weex开发-使用weex-ui绑定事件源注意事项
weex开发-使用weex-ui绑定事件源注意事项
118 0
|
移动开发 JavaScript weex
weex开发 - 方法的映射,在weex调用fetch方法,实际调用同名的原生方法,在回调中把数据传递回js
weex开发 - 方法的映射,在weex调用fetch方法,实际调用同名的原生方法,在回调中把数据传递回js
169 0
|
移动开发 编解码 weex
weex开发 - 加载index.js崩溃,白屏(may it has been destroyed so method:fireEvent is ignored,Url must be passe)
weex开发 - 加载index.js崩溃,白屏(may it has been destroyed so method:fireEvent is ignored,Url must be passe)
255 0
|
移动开发 JavaScript weex
weex开发- 无法找到模块“weex-vue-render”的声明文件。引入vue报错,无法找到引入的vue模块
weex开发- 无法找到模块“weex-vue-render”的声明文件。引入vue报错,无法找到引入的vue模块
256 0
weex开发- 无法找到模块“weex-vue-render”的声明文件。引入vue报错,无法找到引入的vue模块
|
移动开发 前端开发 rax
weex开发android应用
weex使用简要介绍
421 0
weex开发android应用