企鹅电竞Weex实践和性能优化 渠宏伟
Contents 01 02 03 接 入和收益 努 力力填坑 性能优化
H5 页面存在的问题 加载耗时 长 WebView 启动慢 资源加载慢 交互体验差 长列列表滚动 测滑不不流畅
H5 极速加载方案 VasSonic WebView 和 页 面并 行行加载 资源离线预推 页 面局部刷新 动态缓存 H5 页 面 首屏实现秒开 https://github.com/tencent/vassonic
企鹅电竞Weex实践 前端 页 面原 生渲染 增强前端 页 面体验 一次开发 支持三端 Android ios H5 运 行行 提 高开发效率
企鹅电竞 Weex 实践 300 2000 250 200 1500 150 H5 1000 H5 100 50 Weex 500 Weex 0 内存 (m) FPS( 帧 / 秒 ) 0 加载耗时 (ms) 内存降低 45%, 帧率提 高 15.7%; 打开耗时下降 44.9% 开发效率 比终端提升 40%, 有效释放终端开发 人 力力 页 面更更新不不依赖版本发布, 特性发布效率提升
构建流程改造 实际业务 比较复杂, 时常需要在 webview 中增加 一些特殊逻辑 将特殊逻辑 冗余代码打 入到终端运 行行的 JSBundle 并不不合理理
构建流程改造 分离 入 口再引 用相同的 app.js, 可以让 web 版本和 weex 版本保持相同逻辑, 也可以独 立扩展, 互不不影响
接头暗号 头部的 {"framework": "Vue" 告诉解析器器 用 Vue 的语法解析 JSBundle 如果删除了了这 行行注释, 将会 白屏 // { "framework": "Vue" /******/ (function(modules) {... /******/ ) Uglify 压缩会删除注释, 导致 接头暗号 被删除 压缩必须放在插 入 framework 之前 plugins:[ //uglify 必须在 bannerplugin 前面 new webpack.optimize.uglifyjsplugin({compress: {warnings: false), ] new webpack.bannerplugin({ banner: '// { "framework": "Vue" \n', raw: true )
调用终端接口 在 webview 中使 用插 入 iframe 或者 img 的 方式传 schema 协议与终端通信 现有业务有 大量量的 jsapi, 如果全部改造成 module 工程量量很 大 企鹅电竞扩展了了 一个公共的 jsbridge 的 module 用于转发 jsapi, 底层 jsapi 的解析和逻辑保持不不变
获取 cookie H5 中我们使 用 document.cookie 可以获取浏览器器的 cookie 信息 在 weex 中如何实现? 我们利利 用 weex 提供的扩展 Module 的能 力力, 在终端中扩展 一个获取 cookie 的 方法 / 获取 cookies export async function getcookies() { if (typeof document === 'object' && typeof document.cookie!== 'undefined') { return document.cookie else { return await getnativecookie() // 从终端获取 cookies export function getnativecookie() { let datafetch = weex.requiremodule('datafetch') return new Promise((resolve, reject) => { datafetch.fetch('cookie', function (map) { let result = map.result if (result === 0) { resolve(map.data) else { reject(map.message) ) )
支持 cookie ios 基于 UI webview 共享 cookie ios 天然 支持请求带上 cookie android 需要终端 支持, 也能实现请求 自动带 cookie
获取 useragent 在 weex.config.env 添加 useragent 属性 需要注意的是, 从 weex 实例例中获取的 useragent 是静态的 一旦 weex 实例例创建就固定下来, 终端修改 UA 也不不会跟着变化 export default function () { let useragent = '' if (typeof weex === 'object' && weex.config && weex.config.env) { useragent = weex.config.env.useragent '' else if (typeof window === 'object' && window.navigator) { useragent = window.navigator.useragent '' return useragent
如何实现 1px let env = weex.config.env let devicewidth = env.devicewidth let scale = env.scale // 获取布局宽度 export function getpx(pt) { return pt * 750 / ( devicewidth / scale ) // 获取真实宽度 export function getpt(px) { return px * (devicewidth / scale) / 750
横屏适配 function gethwidth (w) { return devicewidth / w * 750 const meta = weex.requiremodule('meta') // 配置 viewport 的宽度为 meta.setviewport({ width: gethwidth(w) // w 为设计稿宽度 )
:class 语法限制 :class="[showbottomborder? 'ui-border-b' : '']" // 只支持数组语法 :class="showbottomborder? 'ui-border-b' : ''" // 不支持三元运算符 :class="{ 'ui-border-b': showbottomborder " // 不支持对象语法
点击态 项 目 比较常 见的点击态多半是透明度的变化, 如按钮 列列表 链接等, css 的做法是添加伪类 (:active), weex 中也同样 支持, 但是 weex 需要在原样式中添加 opacity:1, 否则点击后回不不到初始状态 ; 此外,:active 使 用时,backgroundimage 在 ios 下会失效 <template> <div class="ui-btn"> <text class="ui-btn-text"> 下载 </text> </div> </template> <style scoped>.ui-btn{ opacity: 1; /* 必须添加 */.ui-btn:active{ opacity:.5; </style>
文本截断 文本从限制 1 行行到不不限制可以 用 lines:0 <template> <text class="info-text" @click="textclick" :style="textstyle"> 城市赛战报, 王者荣耀 城市赛郑州站欢乐落幕城市赛战报, 王者荣耀 城市赛郑州站欢乐落幕城市赛战报, 王者荣耀 城市赛郑州站欢乐落幕城市赛战报, 王者荣耀 城市赛郑州站欢乐落幕 </text> </template> <style scoped>.info-text{ lines:1; text-overflow:ellipsis; </style> <script> export default { data(){ return { textstyle:{ ;, methods:{ textclick(){ this.textstyle = { lines:0 </script>
圆角抖动问题 问题存在于android下 weex sdk 配合在新版本weex sdk解决了了这个问题
终端 crash 问题 Android ios OOM PaintDrawable 在 API 21 下偶现渲染 crash Bitmap 回收后继续使 用导致 crash instance 被销毁后调 用 Toast 的 NPE 问题 WXThread.secure 反射调 用异常 未显示禁 用estimatedRowHeight 导致 tableview 在更更新数据源时偶现 crash 布局时 node->get_child 返回空指针导致 crash text component 渲染和测量量 高度时偶现 crash Android 接 入 Weex crash 率 0.13% -> 1.01%
自动化测试方案 生成的终端 view 中的 id 是 weex sdk 自动 生成的 自动化测试系统 无法识别 借助 无障碍化 arialabel 属性作为原 生 view 自动化测试标签 <div :accessibile= true arialabel= pageend index div 游戏首页 "></div>
数据缓存优化 1 使 用 storage 缓存接 口请求数据 2 优先使 用本地缓存数据, 同步请求更更新缓存数据和 页 面 /** * @desc 缓存辅助函数 */ export function cachehelper(key, fetchhelper, callback) { log(' 开始获取 storage:' + Date.now()) getstorageitem(key).then(result => { // 命中缓存, 优先使用缓存 callback && callback(null, Object.assign({, result, {'$_thisiscache': true), true) // 命中缓存后, 拉取数据更新 fetchdata(key, fetchhelper, callback) ).catch(err => { // 未命中缓存, 拉取数据 fetchdata(key, fetchhelper, callback) ) function fetchdata(key, fetchhelper, callback) { fetchhelper && fetchhelper.then(data => { setstorageitem(key, data) // 设置缓存 return data ).then(data => callback && callback(null, data)).catch(err => callback(err))
数据缓存优化
jsbundle 预缓存优化 1 在现有的 weex 页 面配置 文件的基础上增加 一个字段 preload, 当此字段值为 1 时候, 对 jsbundle 文件进 行行预缓存 2 提供 js api : [ ] game_index:{ is_weex: 1. weex: 'http://cdn.egame.qq.com/game-weex/weex/game-index/app.js?v=518', web: 'http://cdn.egame.qq.com/game-weex/page/game-index.html', preload:1 biz/preload 提供给前端进 行行对下 一个 页 面的预加载 biz/clearproload 用于前端对于既有缓存内容的清空 3 对于缓存内容, 使 用 LRU 的算法进 行行管理理, 控制缓存总 大 小为 20M 4 对于使 用缓存的内容, 终端在 ua 上添加 一个字段 PRELOAD/1 ; 1 表示是预缓存内容, 0 表示不不是
jsbundle 预缓存优化
耗时打点统计 1. 拦截请求开始 请求完成 RenderFinish 计算 网络耗时 ( 请求结束 - 请求开始 ) 终端渲染耗时 (RenderFinish - 请求结束 ) 2. 终端通过 js api 提供前端创建 instnace 时间点 3. 终端 前端两份上报, 相互校验数据
终端接口调用耗时优化 1 Android 升级 weex 0.16 版本 module 接 口调 用耗时 大幅减少 2 减少启动 页 面时并发调 用 module 接 口 版本初次调 用耗时 二次调 用初次回调耗时 二次回调耗时 0.12.0 50-60 30-40 10 10 0.16.0 5-6 2-3 2 2 3 Android 调 用时多次反射获取类名导致 Dom 渲染耗时过 长
Android Bitmap 内存优化 版本 crash 率主要 crash 3.1.0 0.13% 系统 crash, 业务逻辑错误等 3.2.0 1.01% OOM SIGSEGV(SEGV_MAPERR) 使 用 Fresco 管线加载图 片, 加载后不不持有图 片引 用 问题 : a 会将 用户当前不不展示的图 片也加载到内存中, 实际占 用内存变多,OOM 问题严重 b 引 用不不被持有会导致 Bitmap 被回收后仍然被使 用 (3.2-3.4 版本 top crash SIGSEGV (SEGV_MAPERR)) 优化 : 仿照 Fresco 的 DraweeController 管理理 WXImageView 的 bitmap 引 用 显示时加载, 隐藏时解除引 用等待回收 OOM 问题明显缓解,bitmap 被回收的 crash 问题也得到解决
GPU 过度绘制优化 1 尽量量不不要设置背景 色 2 不不要过度嵌套, 结构尽量量扁平化
Weex 实践分享 内部影响力
希望优化的问题 横竖屏切换方案支持 支持 armabi-v7a 的 so 包 组件统一开源 : 例如 jscore 内核 debugger gcanvas 更好的性能细分统计 高效的终端和 Weex 共享动态数据方案 更好的容错 : ios JS call Native 时, 参数传错会造成终端 crash
https://weex.apache.org