作者:别志华、祁强
GaiaX 跨端模板引擎,是在阿里优酷、淘票票、大麦内广泛使用的 Native 动态化方案,其核心优势是性能、稳定和易用。本系列文章《GaiaX 开源解读》,将带大家看看过去三年GaiaX的发展过程。
GaiaX 开源地址:https://github.com/alibaba/GaiaX
GaiaX的起源
GaiaX是为了解决多端卡片化UI组件的研发效能瓶颈问题孵化而来的,在过去三年中经过多次迭代,逐步完成了从设计研发一体化到模板研发体系的演进工作。
就像大部分优秀的开源框架一样,GaiaX是从优酷自身的业务特色和业务问题出发,提出的一套解决方案,再经过不断提炼和拓展,从而形成了现在的模板研发体系,其目的是帮助设计、开发、测试来提高效率,解决当前优酷App迭代过程中碰到的研发效能瓶颈问题。
下面会从优酷的业务特色、客户端研发效能的瓶颈问题、提出解决研发效能问题的思路这三个方面分别来进行介绍,带大家进一步了解GaiaX的起源。
业务特色
优酷是阿里巴巴文化娱乐集团的核心用户引擎,是中国领先的在线视频平台,现支持PC、电视、移动三大终端,兼具版权、自制、合制、自频道、直播等多种内容形态。
在优酷持续改善运营效率和成本的背景下,优酷App已经通过技术手段支持了电视、移动、车载等多种设备场景,并不断为数千万用户提供更优质的使用体验。通对优酷App业务场景的分析,我们可以提炼出三个主要的业务特色:
内容分发场景为主。优酷App的业务形态主要包含分发场景和消费场景:分发场景的目标是以简单、高效的形式的引导用户前往消费场景;消费场景的目标则是进行视频内容的消费或者会员权益的消费。
卡片化的UI组件。优酷App的UI组件彼此之间具备高度的相似相性、可以被结构化,并且可以组合使用。例如:左图右文的组件、上图下文的组件、单行多列、多行多列、Banner图、多类型组合等。
多屏多设备。优酷App目前支持Phone(Android、iOS)、Pad(Android、iOS)、Mac(iOS)、车机(Android)、电视(Android)等设备,为了降低研发成本和提高迭代效率,研发团队逐渐在这些设备上使用同一份代码,一个UI组件会在多个设备和不同尺寸的屏幕上进行展示,这就对UI组件的实现提出了更多的适配要求。
研发效能的瓶颈问题
我们都知道,想要解决一个问题的前提是将一个问题定义清楚,那么该如何定义优酷App迭代过程中碰到的研发效能问题呢?
软件行业发展至今,各家公司内的软件开发迭代流程虽略有不同但也大致一样,可以将迭代流程分为业务环节、产品环节、设计环节、研发环节、测试环节、发布环节,各个环节彼此配合、相互协作才能顺利将产品发布。
在迭代流程中的各个环节也分别对应着各自的时间周期,不同的时间周期内所做的事和碰到的问题也不一样。一个迭代通常包含的时间周期有:业务周期、产品周期、设计周期、研发周期、测试周期、发布周期。下面分别简要介绍一下每个周期内各自的痛点和瓶颈问题:
- 业务周期:需求变更、紧急需求、下游依赖方排期困难,期望下游依赖方能快速消化需求和上线迭代。
- 产品周期:业务变更频繁、下游排期困难、需求迭代开发需要跟版发布、下游需求吞吐不理想。
- 设计周期:业务和产品需求变更频繁、设计稿缺少规范化、设计稿内容不能复用、设计走查不方便,期望能将设计稿规范化、提高设计稿元素复用率。
- 研发周期:双端开发、需求并发、排期短、跟版发布、设计稿不规范、性能保障,期望能提高组件开发效率、能减少人力投入、需求能快速发布、组件性能能有保障。
- 测试周期:测试周期短、BUG收敛慢、代码改动范围不明确。
- 发布周期:紧急集成导致发布节点不稳定。
当我们将注意力集中到研发周期内,我们的痛点问题就非常清晰且明确:
- 需求开发需要多平台且要多份人力。
- 需求吞吐量不足产品排期需要进行PK。
- UI组件构建过程中复用率低无法快速开发UI组件。
- 设计稿不规范需要开发转义。
- 缺少合适的效率工具协助UI走查。
当问题被定义清楚后,剩下的就是提出方案、落地方案、检查方案效果了。 下面让我们看看GaiaX团队解决问题的思路是怎样的。
解决问题的思路
当综合业务背景和研发效能的瓶颈问题一起来看,可以拆解出来诸多业务需求的要素,这些都是在研发周期内的痛点问题,例如:内容分发、多业务、多屏多设备、UI组件卡片化、UI组件的构建效率、UI组建的复用程度、提高需求吞吐量,这些需求要素都是在解法方案中要有所体现并进行针对性解决的。
解决问题的思路是找到一个具备如下解法要素的技术方案:UI组件可被规则化易于复用、具备跨平台能力可减少人力投入、具备极致的性能可让开发人员不用反复调优、能复用现有优酷的技术栈和技术能力来保证一致性、具备动态性可动态发布需求以满足业务快速迭代的需求、通过简单的处理就可适配多屏幕多设备。
经过一系列调研后,发现市面上并没有比较贴合我们解法要素的技术方案,于是我们开启了自研的道路,理想中的GaiaX应具备以下技术特性,以解决研发效能的瓶颈问题:UI组件模板化、跨平台、媲美Native的性能与体验、动态性、基础组件可灵活插拔、易于适配不同的屏幕尺寸和设备。
在提出方案思路后,下面就是进行方案的落地,这部分内容会在 《GaiaX 开源解读》系列文章的第二篇:《跨端动态化模板引擎详解,看完你也能写一个》中进行详细的进行介绍,也请各位读者持续的关注。
GaiaX技术形态的发展
续接文章的上一节内容,在提出了解决研发效能瓶颈问题的思路之后,在本节内容中讨论和讲述一下GaiaX的技术形态问题。
跨平台技术已经经过了三轮的技术演进,在每轮技术演进中都有各自的代表作和各自的核心理念,下面简要介绍一下:
- 基于WebView的跨平台框架。创建 HTML 并将其显示在App的 WebView 中,对于平台提供的一些系统服务,通过JS Bridge来调用,一个完整HTML5页面的展示要经历浏览器控件的加载、解析和渲染三大过程,这种开发模式开发的App既有原生应用代码又有Web应用代码,因此又被称为Hybrid App(混合应用程序)。
- 以React Native为代表的“泛Web容器方案”跨平台框架。这种方案放弃了WebView渲染,采用原生自带的UI组件作为核心的渲染引擎,所以这种方案的性能比第一代方案要好很多。代表作就是:ReactNative、Weex。这种方案保持了JS作为开发语言,使用JSX进行UI页面的搭建。
- 以Flutter为代表的使用“自绘引擎”的方式来进行UI渲染的跨平台框架。Flutter既不用WebView进行组件渲染,也不使用原生组件进行渲染,它完全搞了一套跨平台UI渲染框架,渲染引擎依靠跨平台的Skia图形库来实现,手机平台只需要提供一块画布即可。同时开发语言使用既支持JIT又支持AOT的Dart语言,既提升了执行效率,也为支持动态化提供可能。
上面三类跨平台技术,没有先进与否的区别,它们都有各自的应用场景和各自的瓶颈问题,在优酷App中也使用到了上面这三类跨平台技术:
- 基于“WebView”的跨平台框架,经常用于营销页面、活动页面,这种快用快消的场景之中;
- 基于“泛Web容器方案”的跨平台框架,阿里内部使用的是Rax,目前常被用于收银台页面、大作业页面,这类对动态性、性能有要求的场景之中;
- 基于“自绘引擎”的Flutter跨平台框架,目前常被用于一些通用二级页之中,这类场景对开发成本、性能有所要求,但对灵活性要求不高。
当了解了这三类跨平台技术以及它们在优酷中的应用场景后,再结合上一节提到的优酷碰到的研发效能瓶颈问题,可以知道这三类技术方案均无法较好的解决碰到的问题,而任何技术的演进都是不断在已有技术基础之上不断揉捏、组合、提取、精炼的,下面让我们看看GaiaX是采用何种技术形态来解决研发效能问题的。
IDE搭建+双端渲染
由于是为了解决客户端同学在App研发过程中碰到的研发效能问题,在技术形态上考虑了统一性、一致性、易用性、可拓展性、动态性之后,GaiaX决定采用自定义DSL来搭建UI,并使用Native原生UI组件进行渲染的技术形态。自定义的DSL被称作模板,其中包含三个子DSL:一个用来描述UI元素之间的层级和嵌套关系 - index.json;一个用于描述UI元素的样式和布局信息 - index.css;一个用于描述视图元素的数据绑定信息和动态扩展信息 - index.databining。
自定义DSL好处多多。模板可独立存在,这样可以通过网络对模板进行下发和更新,来达到动态更新模板的目的,从而解除常规开发中渲染产物对UI描述信息的耦合。样式的描述使用的是标准CSS规范,这样不仅业务方更容易接受和理解,也为将渲染产物拓展到H5、小程序上留下了可能性。模板可自由扩展能力边界,这也为后来增加JS逻辑留下了口子,也能让模板在一定情况下有更强的动态性。除了以上这些,为了减少开发人员的使用成本,也为了降低SDK的维护成本,GaiaX团队也提供了用于模板搭建的IDE,使用方通过拖拽、搭建就能构建出自己期望的UI模板。
至此,一个使用自研IDE搭建模板并使用Native原生UI组件渲染的技术形态就此产生,由于从搭建、到解析、再到渲染都掌握在自己手中,优酷App迭代过程中碰到的研发效能瓶颈问题都可以得以解决。
动态化能力
上文中我们详细说明了GaiaX的基本技术形态,但其中对动态化的能力却未进行详细说明,相信很多读者对这个部分都很感兴趣。在GaiaX中,将动态化的能力分成了三类,分别是模板的动态化、模板的弱逻辑动态性、模板的强逻辑动态性,每类动态化的能力都解决了不同场景的问题,并且可以被渐进使用,下面分别介绍一下:
- 模板的动态化:模板是一个UI信息描述的集合,当被下发到客户端后其内容就无法被改变了,如果有了紧急需求导致UI内容布局方式和内容发生了重大的变化该怎么处理?为了解决这类问题,我们为模板赋予了版本号的概念,只需要将模板在IDE中重新进行编辑、上线、发布,就可以将新模板下发到用户的App中,来完成模板的动态更新,从而达到UI动态更新的目的。
- 模板的弱逻辑动态性:在一些常规需求中,经常需要根据一些条件隐藏或显示某些区域,或者根据数据改变文字的颜色、字号、大小等。对于这类常态化的需求,我们在数据绑定文件中,提供了使用表达式进行计算的能力,来达到根据数据动态改变UI样式和显示内容的目的。
- 模板的强逻辑动态性:在一些更为复杂的需求中,不仅需要和服务端进行交互取回数据,也需要进行更为复杂的业务逻辑处理和UI交互处理,这种情况在数据绑定文件中使用表达式处理往往无法很好的实现需求,此时就需要更为强大的逻辑处理能力了。为了解决此类问题,我们引入了JS引擎,其专用于复杂逻辑的处理,由于JS引擎不参与到UI绘制逻辑,其对模板的加载和渲染性能都是没有负面影响的。
GaiaX动态化能力就全部介绍完了,在合适的场景选用合适的技术方案,才能用最少得人力完成业务需求,从而提高研发效能。
容器化能力
上面两节提到了GaiaX的渲染能力和动态化能力,作为跨平台的技术方案提供给业务方基本上已经够用了,但是为了更进一步提高复用性和降低研发成本,我们又提出了容器化的概念,进一步封装了GaiaX并根据使用场景将其分为三种类型:
- 第一种类型:业务方不需要编写任何Native代码,仅需要搭建和配置模板,通过使用容器中的自动埋点、自动路由、预置事件等能力,就能实现业务二级页、非核心的频道页以及一些静态组件、坑位的开发和上线工作。这个部分核心在于增强容器的各种原子化能力,例如:埋点、路由、事件、氛围、暗黑模式等,让业务通过模板编辑和配置就能完成UI搭建、逻辑处理、事件处理。
- 第二种类型:业务方通过继承或者包含插件的形式,写少量的Native业务代码,通过增加一些自定义的配置,就能支持业务的频道、组件、坑位的开发。这个部分的核心在于容器层能够提供可扩展的能力,能让业务自定义实现。
- 第三种类型:业务方需要写部分Native代码,用于处理特殊业务逻辑,再配合自动埋点、自动路由等原子化能力,来时实现业务迭代。
三种容器化类型的作用域彼此配合,基本可以覆盖业务迭代中的大部分场景,通过借助使用GaiaX容器化的能力,业务方可以不直接使用GaiaXSDK,不仅降低了学习成本,也能再一次提高研发效率。
配套设施的增强
GaiaX在优酷落地的过程中,也碰到了模板查验效率低、模板开发效率低的问题,为了解决这些问题并造福开发和测试,也分别提供了实时预览工具以及设计稿D2C的功能。
使用实时预览工具,可以让开发者在IDE上搭建好模板后,通过扫码的方式,将模板渲染在目标设备上,并且可以随着IDE的改动实时更新UI效果,类似于Flutter的热更新,这样不仅更直观、也能让模板的开发效率更高。
使用设计稿D2C工具,可以让开发者将设计稿直接导出成模板文件,省去了模板中一部分的搭建工作(例如:层级结构和样式调整),开发者只需要处理数据绑定逻辑和UI更新逻辑,即可完成模板UI组件的开发,让开发效率再上一个台阶。
除了实时预览工具和设计稿D2C工具外,GaiaX还提供了模板管理器、Ribut抓包与Mock神器、数据监控等配套设施,让GaiaX模板研发体系更为完整,进一步推动解决研发效能的瓶颈问题。
GaiaX开源项目规划
GaiaX目前已经在Github上开源(https://github.com/alibaba/GaiaX),并且在紧锣密鼓的迭代开发中。此外,我们也规划了未来几个月的项目路线图,以便让感兴趣的同学了解我们的动向。
系列文章
《GaiaX开源解读》系列文章预告如下,欢迎持续关注:
- 已上线《基于优酷业务特色的跨平台技术》
- 已上线《跨端动态化模板引擎详解,看完你也能写一个》
- 《给Stretch(Rust语言编写的跨平台FlexBox布局计算库)新增特性,我掉了好多头发》
- 《表达式作为逻辑动态化的基础,我们是如何设计的》
- 《向经典致敬 ReactNaitve与GaiaX渲染核心技术分析》
- 《为了保障双端一致性,我们做了哪些努力》
- 《一条龙的模板研发体系,你不来看看么》
团队介绍
我们来自优酷产品技术与创新中心应用技术部,从日常工作中真实存在的研发效能及痛点问题出发,我们自研推出了GaiaX动态模板技术体系,目标是解决多端卡片化UI组件的研发效能问题,帮助提升开发者体验及效率。目前GaiaX项目已经在GitHub开源【https://github.com/alibaba/GaiaX】,也殷切的希望广大终端(移动端及前端)技术爱好者与我们进行技术交流与共建。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。