今天在移动端,尤其是像手机淘宝这样的 App 中,动态性问题逐渐成为一个比较棘手的问题。所谓动态性,就是把移动应用本身的灵活性、迭代更新的周期和成本优化到极致。比如手机淘宝的店铺首页,它允许商家实时装修自己的店铺,更新自家的商品、活动等信息;再比如淘宝、天猫每次大促的会场页面,要求我们非常灵活的及时调整界面信息和状态,确保在瞬息万变的活动当天紧跟促销节奏,应对各种突发情况。
动态性需求的出现有很多必然的因素:我们的移动应用背后是一个平台级甚至是生态级的电商系统,它需要有海纳百川的能力和高速流通的特点,市场上很多移动应用也有类似的客观形态和诉求;同时整个行业迄今为止在移动端的积累都还不足以对产品形态、用户体验、交互方式等细节有完全的前期把握,一个移动应用,客观上需要更多的尝试和探索,甚至是“试错”,而这种动态化的程度和产品迭代演进的速度有着强烈的正相关;第三,我们不必要为这些动态性在多个端投入重复的精力,更不应该因此而频繁的触发新版本。所以动态性问题在今天的移动端显得尤其重要。
动态性问题不只是移动端特有的,在互联网技术发展的历史长河中,桌面端也存在并经历着类似的事情。今天桌面端的结论似乎已经形成,那就是W3C长期倡导的WebPlatform (或被称为 Web App 或 HTML5 或浏览器),然而这也经历了去平台差异化、native插件支持 (flash player)、设备性能提升、渲染引擎优化等过程。
而在移动端,阿里巴巴的无线事业部、兄弟团队、以及整个行业都在做着各种积极的尝试和实践:
Hybrid方案:以WebView为容器,以HTML5为基石,通过定义native特性的扩展来支持的动态化产品研发,比如手机淘宝内部的名为WindVane的容器,这类方案通常具有非常高的动态性,但存在的问题和动态性本身一样明显,那就是性能和展现效果上的不足,而且想把其优势在工程中充分发挥出来,对开发者在前端知识和经验上的积累也有较高的要求,篇幅有限不做过多的展开。
结构化native view方案:以native view为容器进行 native 级别的渲染,并定义一套描述视图结构的数据格式 (如 XML 或 JSON 等) ,然后通过动态改变或请求新的这样的数据信息达到动态化的界面效果,比如阿里巴巴集团内出现 (过) 的 WeApp、鸟巢、Dynative、PageKit 等,这类方案依赖一个结构化的界面描述,并重点保障纯展现输出维度的动态性,各有千秋,但有一些共性的不足之处,比如对其它维度的动态性处理,比如逻辑的动态性,加载策略的动态性等。
React Native方案:大家习惯简称其为RN,以native为渲染引擎,通过脚本引擎支持界面Virtual DOM的转换和逻辑控制,来实现界面的动态性。RN 前半年在阿里很多团队都得到了实践,包括我所在的无线事业部,但效果并不令人满意,首先是RN量级非常重,在请求、加载、渲染、交互、稳定性等层面都不够理想,而整个技术方案在社区的迭代和演进过程也一直充满着不确定性,这给团队产品级别的运用和后期跟进带来了很大的困惑。
实际上,我们觉得 RN 更像是一个全新的移动开发框架,而不是为了增强现有移动应用的动态性而生。大家希望通过 RN 解决动态性问题,是因为它在客户端引入了 JavaScript 引擎而已。
综上所述,我们能够看到很多中动态性问题的解法,但也都各有所限。团队经过不断的观察和讨论,决定拿出一套更好的更针对移动端动态性问题的技术方案——这就是今天的 Weex!
Weex 在我们看来已经具有非常多的特点,比如:
致力于移动端,充分调度 native 的能力
充分解决或回避性能瓶颈
灵活扩展,多端统一,优雅“降级”到 HTML5
保持较低的开发成本和学习成本
快速迭代,轻量实时发布
融入现有的 native 技术体系
工程化管理和监控等
……
但是 Weex 其实最核心的诉求就是解决移动端动态性问题,它有自己非常鲜明的三大特点:
轻量:体积小巧,语法简单,方便接入和上手
可扩展:业务方可去中心化横向定制组件和功能模块
高性能:高速加载、高速渲染、体验流畅
Weex 为移动端动态性问题而生,这些优势都是天然的,追求极致的。团队基于这三方面设计并实现了整套技术方案。
团队在 Weex 的设计和实践中,还有一个很深刻的感悟,就是:找到性能与动态性之间的平衡点。
放眼这么多动态性技术方案,有这么几个必经之路:
动态内容的开发/配置
动态内容的云端部署
客户端请求动态内容
客户端把动态内容现成最终的效果
如果我们不只是处理纯展现性质的动态性内容,那么要再加上一个必经环节
动态内容的开发/配置
动态内容的云端部署
客户端请求动态内容
客户端把动态内容和逻辑解析成视图
客户端把视图展现成最终的效果并处理用户交互
这里面哪些环节值得扩展、哪些环节需要更多的动态性、哪些环节是性能的瓶颈,是整个解法的关键。通过思考和讨论,我们不难发现:
动态内容的开发/配置需要快速实现
云端部署需要尽量去中心化,横向可扩展
客户端请求需要尽量小的传输数据,需要尽量快的加载过程
客户端内容解析需要动态性
客户端交互响应需要动态性,需要尽量去中心化,横向可扩展
客户端界面渲染需要高性能,需要尽量去中心化,横向可扩展
所以我们的解决方案中有几个关键决策:
在内容开发/配置和云端部署之间需要有 transformer 的转换和处理能力,平衡开发体验和客户端请求的数据量
客户端需要有 JavaScript 引擎,处理动态逻辑,提供动态加载策略,同时需要将复杂的端上的解析工作尽量提前
动态内容的描述需要有结构、样式、数据、行为的分离,保障复杂的内容可分解
客户端界面渲染需要 native 的渲染能力,保障性能
Native 渲染和 JavaScript 引擎之间的边界放在了 Virtual DOM,两者通过约定 Virtual DOM 来进行通信,而不是 template + data 或是别的边界,确保渲染性能和灵活度的平衡
动态内容发布、客户端接入、组件、JS API 全部需要横向扩展性,保障 Weex 的核心足够轻,足够专注,同时竟可以支持更多的业务场景
Weex 核心设计理念是三端一体化的动态化解决方案,云端同学实现实时发布和动态部署、模版预解析处理,前端同学在 JS Framework 实现动态内容解析并处理成 Virtual DOM,客户端同学提供渲染实现和 native 特性的支持,接下来业务同学根据 DSL 实现动态内容的开发或配置即可。
Weex 在 DSL 设计上大量借鉴了 Web 标准的规范,并且通过主流且成熟的 MVVM 模式书写 template、style、script,我们在学习成本、开发习惯方面为业务同学考虑了很多,这样的话业务同学可以很快的学习和上手,并且保证代码的规范性和可读性 (这里要特别鸣谢一下 Vue.js 及其作者尤雨溪,我们在上层 DSL 的设计和 JS Framework 的实现上都做了深度的使用和借鉴,也在和作者的交流过程中受益匪浅)。
其次为了提升性能,减少客户端的性能损耗,Weex 在服务器端实现了 DSL Transformer 的工作,可以在模版发布的同时,将 XML + CSS + JavaScript 代码转换为可以小数据量执行效率高的 JS Bundle,并同步存储至云端:如 Web Server、CDN 等。
再次为了保证业务逻辑的动态性,Weex 在客户端的 JavaScript 引擎中预运行起了一套 JS Framework,来负责解析整个 JS Bundle,而 native 端则只负责 Virtual DOM 的解析和布局、UI 渲染的实现、以及基础网络通讯、文件读写以及手势处理等基础 API 的实现。
还有为了有效的提升工作效率,Weex 的 JS Bundle 可以实现三端跨平台渲染展示,业务同学可以通过开发一份 Weex JS Bundle,来实现 iOS/Android/HTML5 三端的正常展示。
所有的 native 组件和 JS API 全部都是模块化的,业务同学可以通过注册新的模块和方法达到去中心化的能力扩展。
关于 Weex 的性能优化还有以下几个细节:
JS Framework 通过对数据的依赖收集,实现响应式的视图层,再加上一层 diff 算法的优化,可以有效的过滤冗余的操作和复杂的计算。
Native 端对通信,Virtual DOM 解析以及布局实现等进行异步线程的处理,防止 UI 线程的阻塞。
对 UI 组件节点实现了复用处理,并对图片资源进行监控和回收,有效的减少内存的占用。
对于实时性要求较高的处理,Weex 允许第三方实现 native 的定制需求来保证体验的流畅性。
图:Weex 关键性能测试和同类方案对比
> 注:数据取自实验室测试结果,测试界面为 60 个左右“坑位”的商品列表,测试机型为:
> - iOS:iPhone5 - iOS 9.1
> - Android:三星SM-N9006 - Android 5.0
Weex 在双十一项目中,参与并支撑了的移动端主会场界面展示和动态处理。在云端实现了天猫前端运营发布系统“斑马”的对接,在前端开发实现了主会场的界面模块和业务逻辑处理,同时在客户端上对接了手机天猫、手机淘宝。
在每次双十一中,主会场都是非常关键的一个环节。大量的流量把用户、店铺、商品从各路而来汇聚在这里作为着陆的起点。在内容的复杂度、灵活性、体验等方面都有着极高的要求。根据我们往年的经验,会场的分流能力强化、分会场的层级扁平化、运营工作量合理化、体验和性能的优化,是非常重要的几个细节,同时也推演出了今年主会场的三大改进目标:
体验 app 化
层级扁平化
内容个性化
体验 app 化意味着我们需要有超越传统 HTML5 的性能和体验;层级扁平化意味着每一层的内容会更加丰富和复杂,主会场当然也不例外;内容个性化则需要我们在前期内容的产生、算法、投放、客户端内容加载和界面呈现等每个环节进行全面升级。
想做到这些,光凭一个好的创意和想法、或凭借员工超强的执行力、或靠砸钱砸机器,都是没有办法做到的,这个问题需要技术驱动力来解决!需要精密的设计和实现。Weex 团队在整个双十一的筹备过程中和需求方就上述问题进行了深入的沟通和交流,并拿出了切实有效的技术方案,很好的解决了其中的很多关键环节问题,并且 Weex 作为一个新的技术方案很好的经受住了如此重要的“考验”!
首先,我们通过 Weex 实现了在双十一主会场的 iOS/Android/HTML5 的一次开发,多端同步展示能力,并且展现效果和各方面的体验都是 native 级别的。
第二,我们配合算法团队实现了今年的双十一主会场的个性化需求,即所谓的“千人千面”,并实现了双十一主会场商家的运营配置的静态数据和个性化推荐算法的动态数据在端侧的拼合展示。并且优化了整个客户端内容加载、界面初始化、交互时的性能
第三,Weex 保有了接近 HTML5 的灵活调整发布机制,实现了在客户端侧的渲染动态性,运营人员可以通过配置实时调整主会场楼层位置,以及“坑位”的排布,以及界面的布局展示和样式调整。
第四,基于优异的性能表现,在内容呈现的数量上,我们也突破了传统的 120 “坑位”的性能极限,本次双十一最后实际的最大“坑位”数接近了 180 个,依然表现非常完美——要知道团队在前期都是拿 300 个“坑位”进行“暴力极限测试”的。为会场的扁平化进一步提供了保障。
目前 Weex 已经在阿里巴巴集团内和更多的业务方展开合作,包括淘宝双十二等项目 (笔者撰稿时恰逢双十二当天,Weex 正在接受新一轮的业务洗礼!),我们希望后续会有更多的实践经验和心得持续分享出来。
未来 Weex 除了继续服务于会场这样的需求 (如双十二、年货节等) 之外,更希望可以支持到更多的动态化场景,并围绕 Weex 的核心优势不断解决更多的问题,甚至不仅解决动态性这个历史难题,还可以进一步解决跨端重复开发、用户体验一致性、容器通用技术规范等问题;甚至不仅解决手机淘宝、手机天猫的问题,还可以解决阿里巴巴兄弟团队、国内甚至行业内的普遍问题;体现出更大的价值!当然这一切看起来天马行空的梦想需要我们脚踏实地的一步一步走出来,始终保持清醒的头脑,围绕 Weex 的核心价值,聚焦在核心的问题上,也非常希望可以借助整个大团队、整个集团乃至整个技术社区的力量。
Weex 团队会紧抓移动端动态性这个关键命题,围绕 Weex 的三大特点:轻量、高性能、易扩展,进行周期性的迭代和完善。我们会在更简单直接的实践方式、更高的加载/启动/渲染/交互性能、更强的去中心化定制性和横向扩展性方面不断突破和创新。并定期在集团内开放最新的版本和文档、配套工具、周边生态等。
随着 Weex 新版本的不断迭代,我们同时也会面向集团范围内的业务方,采取更开放的沟通和服务策略,深入到业务中,了解大家在实践中的真实诉求和痛点,同时提供 Weex 的技术支持。在保障 Weex 的实践效果和产出的同时也会汲取更多信息和灵感作为后续 Weex 努力和完善的重要参考。
团队在长期的迭代和业务支持上会逐步找到一个稳定的节奏,并且做好打持久战的准备。随着工作的进展和不断深入,我们相信 Weex 可以走出一个“扇形”,并一步步的实现大家期待种的宏伟蓝图和远大设想。
关于开源:团队始终认同一个观点——开源并非一个简单的行为,而是一个过程和最终的结果构成的整体。团队希望 Weex 能够逐步解决更普遍的业务问题,尽可能的保障工程质量和代码质量,并发展成为能够被社区接受、参与和信赖的技术方案。体现更大的价值,同时得到更多的支持和更快的发展。这是我们希望的,也希望是大家希望的:)