JxMY 2019-06-28
出于对开发效率和动态化的要求,无线端的开发框架也一直在更新,从 Hybrid、结构化 Native View、React Native、Weex,再到现在正在大受关注的 Flutter。什么样的框架才是适合自己的团队?不仅要有技术追求,而且要考虑实际业务需要。最近,有赞移动选择了 weex 作为无线开发框架,搭建了从开发、Debug、构建、发布、数据一个闭环的流程。本文将对此进行分享。
Weex 是阿里巴巴开源的一套构建高性能、可扩展的原生应用跨平台开发方案。首先总结一下 weex 的特点:
Weex 也不是只支持 Vue 和 Rax,你也可以把自己喜欢的前端框架集成到 Weex 中,有一个文档扩展前端框架描述了如何实现,但是这个过程仍然非常复杂和棘手,你需要了解关于 js-native 之间通信和原生渲染引擎的许多底层细节。
前提是都集成了 weex sdk,另外视觉表现做不到完全一样,有的会有一些差异,需要做一下适配。所以写 weex 页面的时候,如果支持三端,便需要在三端都进行自测。
weex 里使用组件都需要在 native 端注册,这样 weex 里才可以使用,运行的时候通过注册时记录的 map 进行查找。weex sdk 内置注册了一些基础的组件,包括 list、text、input 等。WXJSCoreBridge 封装了 JavaScriptCore 实现 native 和 js 之间的通信。
可以将 native 的 UI 组件封装成 component,将 native 的逻辑代码封装成 module。从而在 weex 里可以进行使用。这里的 natiev UI 组件包括 modal、webview、image 等,这里的 native 逻辑代码包括 storage、network 等。
1)开发的人力成本
如果不算 web 端,一个页面本来需要 Android 和 iOS 2 个人开发;使用 weex 后只需要 1 个开发页面。
2)开发的编译速度
随着项目渐渐变得庞大,Android 项目一次编译需要 2-3 分钟,机器不好的还需要 10 分钟,iOS 可能会快一点,也需要 1-2 分钟。使用 weex 后,界面修改,只需要十几秒。
3)测试效率
提测之后,发现 bug,修复完成,测试总需要重新下载一个包进行安装;使用 weex 后,跟原生无关的 bug,只要测试重启 App 就可以进行验证。
weex 页面最后打包完是一个 js 文件,只要能做到动态下发 JavaScript,那便可以实现动态化,可以热修复,甚至可以热部署,完全替换或者新增页面。
在 2016 年阿里双十一中,Weex 在阿里双十一会场中的覆盖率接近 99%,页面数量接近 2000,覆盖了包括主会场、分会场、分分会场、人群会场在内几乎所有的阿里双十一会场业务。阿里双十一主会场秒开率97%,全部会场页面达到 93%。
2016 年 12 月 15 日,阿里巴巴宣布将移动开源项目 Weex 捐赠给 Apache 基金会开始孵化。
2017 年,weex 在阿里业务里增长如下图,来自 WeexConf 2018。
经过实践,一个移动端开发,一周时间就可以开始进行使用 weex 进行业务开发。
weex 其实是一套方案,各个流程很多东西需要自己建设,把它建设得让小伙伴可以以较小成本开始使用 weex,把它建设得融入已有的系统。这方面,我们目前做了下面这几个方面,还任重道远。
这是一个脚手架工具,基于 weex 官方的 weex-toolkit,用于新建 weex 工程,目前只支持 vue。
随着页面的增多,业务的复杂,工程会慢慢变得庞大,每次运行的时候如果全部页面都运行起来比较慢。为了解决这个问题,使用 zweex-toolkit 创建建的工程模板支持运行的时候,支持只运行指定目录下的页面,只要在 npm start 后加上参数即可,如:
npm run start hi,helloworld
这样就表示只运行 hi 目录下和 helloworld 下的页面。
另外,我们支持:
zweex page
zweex debug
官方 weex sdk 做的事情,就是输入一个 js 文件,然后返回一个view。考虑到每个应用的路由和个性化的需要,这一点,ZanWeex SDK 没有做其他工作,也还是返回了一个view,业务方可以根据自己的需要将view添加到自己想要展示的地方。ZanWeex SDK 做的事情主要有如下几方面:
1)支持下发配置,支持动态化,可以完成整个页面的替换
weex 页面打包后的结果是一个 js 文件,所以可以进行下发进行动态更新,那么就需要有一份配置,来关联页面路由和 js 文件的关系,于是我们设计了这样的数据结构:
h5:页面路由地址,可以直接使用发布平台生成的 h5 地址
js:打包后的 js 文件地址
version:支持的最低 App 版本,因为新页面如果需要 native 扩展,那就需要发布新版本进行支持
md5:为了校验完整性,我们在配置里添加每个 js 文件的 md5。
2)支持多模块独立配置,互不影响
一个App里会有多个模块,每个模块可能由独立的团队进行负责,所以为了减少耦合,我们将配置独立,每个模块可以独立管理自己的配置,独立接入weex,不依赖于宿主App。
3)预加载页面模板,支持页面模板缓存和配置缓存
4)支持开发时的hot reloading,前端开发般的体验
5)支持页面的适配,提供环境变量
ZanWeex SDK 会提供以下四个变量共 weex 页面使用,方便完成页面配置。
6)开发阶段日志的查看
在开发阶段,weex sdk 源码里输出的日志以及 js 里通过 console.log 输出的日志,还有 js 运行的报错,都只能通过 XCode 和 Android Studio 进行查看。这对于一个只了解一端的开发人员是非常不方便的。于是我们做了一个入口,在打开 weex 页面的时候,会显示该入口,点击即可查看所输出的日志。
7)参数传递
正向传参:从 A 页面跳转到 B 页面,参数传递是开发过程肯定会遇见的一个场景。SDK 对外提供的渲染接口 renderByH5 的参数包括 url,params,data。业务方进行渲染的时候,可以将参数直接跟在 url 后面,或者通过 params、data 传入,不同方式,取的方式也不一样:
前面有提到,weex 的页面目前可以采用 vue 或者 Rax 编写。对于 Vue 和 Rax 的语法这里不做陈述。这里主要总结了容易在实际开发中卡住小伙伴的几个问题。
1)如何判断一个页面是否用 weex 来实现?
可以认为所有的新页面都可以采取 weex 来开发,区别在于这个页面使用的 native 能力有多少。可以通过自定义 Module 来调用 native 的能力,通过自定义 component 来使用 native 的组件;
2)什么时候需要自定义 Module?
需要原生的能力的时候,比如:
调用已有的业务逻辑,比如:
3)什么时候需要自定义 component?
4)多个弹层的布局如何实现?
weex 页面渲染的层级,是从上而下的,越在下面的布局,显示越上层。所以要作为弹层的布局,就把它放到最下面。
5)页面的动画如何实现?
官方 weex sdk 已经封装了 animation 的 module 可以直接使用,复杂的动画可以使用 BindingX 实现。
6)weex 的代码如何复用?
代码都可以抽离出组件。
我们开发了以项目为单位的构建平台:
我们还开发了以应用为单位的 weex 发布平台:
在开发过程中,很多问题,可以通过阅读源码来解决,比如:
答:已支持,包括内存缓存和文件缓存,内存缓存使用 familyname 来做 key,文件缓存使用 md5(url) 来做本地文件名
答:module 的函数氛围 UIThread 和 JSThread,JSThread 对于 js 线程来说是同步的,支持直接返回参数;UIThread 对于 JS 线程来说是异步的,不支持直接返回参数,只能使用 callback
另外,很多常见的问题,我们已经在 ZanWeexSDK 进行了解决,包括实现动态化、多模块的支持、缓存管理、Hot Reloading、日志查看、页面适配、参数传递等。
此外,还会有一些常见的问题,在此罗列一下:
答: 配置的更新接口开放给业务方调用,由业务方决定什么时候调用更新接口;SDK 里做了三种处理,来尽量保证配置可以更新成功:
1)配置接口拉取失败后,会有三次重试;
2)网络从无网变成有网时,sdk 会检查配置是否已拉取,如果未拉取就主动拉取
3)允许业务方内置配置和 js 文件,当拉取失败后,SDK里会从内置配置里读取
答:配置每次发布的时候,都会指定该发布支持的 App 最低版本号。每次请求,会携带 App 版本号,服务端只会返回符合该版本号的最新配置。
答:答案是支持的。旋转之后,屏幕变成了横屏,weex 就按照横屏的尺寸来渲染,问题是只要你写的页面符合这种变化就可以了,跟 native 来实现页面没有什么区别。