淘宝双促中的 RAX

简介: 在2017年1月12日 Weex Conf 2017上,来自淘宝前端团队的亚城结合淘宝实际业务分享了淘宝双促中的RAX实践,在本次 Weex Conf 上正式开源的 RAX 是基于 React 标准的 DSL 框架。本文是亚城关于淘宝双促中的 RAX 实践的分享整理。
摘要:在2017年1月12日 Weex Conf 2017上,来自淘宝前端团队的亚城结合淘宝实际业务分享了淘宝双促中的RAX实践,在本次 Weex Conf 上正式开源的 RAX 是基于 React 标准的 DSL 框架。本文是亚城关于淘宝双促中的 RAX 实践的分享整理。

以下内容根据演讲现场视频以及PDF整理而成。


本次分享的主题是淘宝双促中的 RAX 。通过前面的两个分享,相信大家大致可以了解Weex 能够赋予我们什么样的能力以及天猫和淘宝在 Weex 周边做的一些的事情,并且应该也大致了解了如何在斑马上面搭建整个链路。本次的分享将会承接之前的两个分享,并且会主要谈谈淘宝前端团队在整个斑马链路里面进行的实践以及在 Weex 上进行的一些实践。本次首先会分享 RAX 框架提供的基础的一些支持,之后将会分享页面渲染以及整个页面体系的相关内容。

1.RAX

我们首先谈一谈什么是 RAX。RAX 其实是一个基于 React 写法的跨容器的 JS 框架。RAX 首先是基于 React 写法的框架,所以如果大家会使用 React,那么就能够很快地上手使用 RAX;另外一点就是 RAX 框架是跨容器的,如果之前的项目是使用 React 写的,为了使用 Weex 的功能,使用 RAX 框架进行迁移是非常方便的。


RAX 有很多的优势,比如在 gzip 之后,其大小比 React 小了四倍,并且在服务端的渲染方面 RAX 也有非常好的表现。在双十一和双十二促销过程中,RAX 都起到了基础和核心的作用。其实之前总谈到天猫双十一的数据,其实在淘宝双十二会场中也达到了1600个以上的页面,数量如此多的页面其实基本都是使用Rax进行渲染的,并且在双促中,淘宝都是以 RAX 为核心来构建上层的标签和 API 以及 RAX 的 UI 组件、上层的大促模块和大促页面的。

40a6052efb22ec79d23dd218e73c0be06fb68e09


2.RAX 对于大促的基础支持

接下来简单介绍一下 RAX 对于大促的基础支持。其实除了像天猫双十一、淘宝双十二以及现在的年货节等大促活动以外,还有很多像爱逛街等淘宝使用的很多业务以及独立应用都是使用Rax框架搭建的,但是我们今天主要分享的是 RAX 在双促中的应用场景。

1d900c10d7fa7262e42a6cf7d32d702852790f40

Weex 提供了很多的 API 供大家使用,与此同时我们在 RAX 上面也进行了一层封装,使得 Weex 能够在双促活动中为我们提供基础的能力。而且目前很多东西都已经包含在开源版本里面了,大家感兴趣的可以关注一下。

另外一部分是基础的标签。在整个 Weex 的组件里面其实有 div、scroller、list 等等这样的一系列标签,对应到 RAX 这边也有一套相应的解决方案,比如 div 对应过来是 View,scroller 对应过来就是 scrollView,其实在这里很多的概念是引用了 React Native 的概念,所以如果大家之前的项目是使用 React Native 进行开发的话,就能很方便地享受 Weex 的一些能力。

a1903b547ac40d55b2a9319e76b2da8c23080b71

之后分享一下从标签到整个上层的页面的构建过程。下面这张图中最下层的 Compontents 是我们所提供的最基础的标签,比如 Slider、View、Video,这些都可以映射地理解为 HTML5 基础标签级别最细粒度的标签。

8736a7214c1f2a28a26d449873d81d1995ad012c

在基础标签集合之上分为了两块最主要的部分,一部分是 RAXUI,也就是组件支持,而另一部分就是页面渲染,这两部分将支持整个大促中的统一的应用解决方案。RAXUI 提供了对于图片的播放、视频的加载以及横向的导航切换等通用的解决方案,能够帮助我们快速地完成业务模块。而对于另一部分页面渲染,也就是 rax-page 来说,它所做的事情主要是组织 RAXUI 的组件和模块来达到页面滚动的容器、渲染优化以及完成渲染逻辑,并且实现页面的秒开以及在页面渲染过程中的优化。


在这一层之上就是大促中使用到的模块以及页面所需要的一些组成部分。淘宝的大促页面大致区分了以下的概念:业务上的公用模块以及滚动容器内的一些模块,也就是 APP 级别的模块,而像电梯的内容以及橱窗的内容等,这些都是位于一个通用容器内的,则属于Page 级别的模块。

从基础标签,到通用组件再到上层业务模块,是淘宝大促页面构成的整体思路。

3.淘宝双促中的页面渲染逻辑
接下来来与大家分享淘宝双促的一些实践,主要分享一下淘宝双促中的页面渲染逻辑。

在整个 rax-page,也就是淘宝渲染核心的组件里面包含了如下图所示的这样的几个主要的组成部分。

dcb2ffacd35208ab41c69437190f4d4bb3170cb9

Page 提供了整个页面的一个包裹容器,这个容器用来抹平 HTML5 与 Weex 之间存在的一些差异,使我们能够得到一个完全一样的外层的包裹容器。在 Page 内部将会放有一个 Block 标签,Block 标签是用来做页面滚动的。在很早之前的版本中,Block 标签还是用 scroller 来实现的,但是在双促里面,为了达到更好的性能,我们使用了 List 来实现 Block 标签。使用 Block 这样的页面滚动容器一方面也是为了抹平 HTML5 与 Weex 之间的存在的差异,另一方面就是我们提供了一套统一的为斑马进行渲染的渲染逻辑,来达到页面秒开的效果。

接下来是模块的组织,也就是页面模块这一层。对于这一层而言,在淘宝的每一个斑马模块的外层,都会进行包裹,也就是实现了 Module 的逻辑,其里面将会处理模块级别的埋点,并且对于大促的细粒度的拆分等进行优化,很多模块级别的处理将会放在这一层实现。 Link 是一个业务级别的埋点,之前的分享到了天猫里面的很多的埋点是自己拼的,而淘宝这边则提供了业务级别的埋点标签,也就是 Link 标签,这个标签所做的就是通过自动化的方式帮助用户实现埋点,也就是将原本用户需要手动实现的埋点做成标签进行实现。

下面还有事件通信,如果大家开发过 React Native 或者 React 的话,就会很容易理解。RAX 框架里面的事件通信是通过使用的 React 里面的 Context 上下文实现的,对页面的每一层进行绑定之后,业务下面的每一个模块、模块与模块之间以及模块与整个页面之间都可以进行事件的消息收发。这个机制在淘宝的双促中也有很多的应用,包括下拉刷新以及页面内弹层等等。

以上这些标签都是组成页面核心渲染逻辑的部分,有了这些标签接下来就可以使用它们对接整个斑马平台,并且使用渲染逻辑对于模块进行渲染。

在模块组织方面,则主要分为了两种类型:滚动容器内的模块以及页面级通用的模块。这个里面形象到页面上,其实就是 Block 是一个滚动的容器,在这个滚动容器的内部可以包含很多个业务模块,比如橱窗、slider 等以及一些其他在浏览页面时需要进行滚动的部分。而另外一部分像通用导航头,以及比如需要在页面顶部或者底部显示的消息,也就是需要不随着页面滚动而发生动作的模块,所以像通用导航头等这样的模块属于更上一个层级,所以将像通用导航头这样的模块都放在了容器外面。在最右边的图可以很好地看出,通用容器其实是页面中的一个部分,而通用导航头却位于 Block 外部。

824c2ec634315ef6fb698cdfbc6480c30d94db10

我们使用双十二大促的一个页面作为例子进行说明。在如下图所示的这个页面中,最上面的是一个通用的电梯,这个通用电梯使用了 tabheader 组件,它所做的事情就是使得导航头吸附在页面顶部,不会随着页面的滚动而滚动,并且可以个根据不同电梯的跳转而跳转到不同的楼层。页面底端的抢红包和返回页面顶部等也是一样的不随着页面变化的,所有的这些都会定义为通用的模块。而这些通用的模块将会放在页面的滚动容器外面,然后像里面的橱窗就是在滚动容器内部的。总而言之,APP 级别的模块不会随着页面而滚动, Page 级别的模块是包裹在页面里面的,需要跟随页面滚动,这两个概念就是构成双促会场大促模块的基本概念。

6a4471188b47f67e04a59485797c15ca759e4d31

页面级别的滚动模块 Block 在双促中是使用 List 实现的。还有就是最外层的框是 Page,这样就基本完成了整个页面的布局。

接下来分享两块比较核心的部分就是双十一以及双十二大促时,在 H5 页面以及 Weex 页面的渲染方面使用的不同的渲染策略。我们都知道使用 Weex 开发所期望的是通过一次编码能够实现在不同容器内获得一致的体验,而在真实的运行过程中,在 H5 页面和 Weex 页面中运行时还是或多或少存在一些差异的。

我们首先简单介绍一下 H5 页面的渲染,后面将会谈到的 Weex 与 H5 渲染的差异是比较大的。先跟大家解释一个概念,就是在 Weex 中,一个 View 的容器或者一个 div 容器其实是有一个 appear 实现的。当页面滚动到这样的页面的一个可视区域的时候,View 容器将会触发其 appear,同样的,我们在 H5 页面中也模拟了这样概念,以此来使得两端具有一致的开发体验。当某一个模块出现在可视区域内触发 appear 事件的时候,我们会将此模块进行渲染,因为在用户刚刚打开这个页面的时候不会将全部的模块进行渲染,而是做了首屏的切分,只有首屏的模块才会在用户刚打开页面的时候进行渲染,非首屏的模块在此时将会是一个高度已经撑开的占位容器。

2ec79675da6c809063af6a3e412c99322e6fdd10

这样渲染逻辑的好处就是在双促里面很多场景下,比如用户想打开首屏以后直接通过通用导航头的电梯跳转到第三层楼或者第十层楼等任何用户想到达的位置,而这些模块此时已经被撑开的情况下,电梯的跳转是不会收到任何影响的。当用户跳转到某一楼层之后,可视区域的 View 则会触发响应的 appear 来渲染其真实的模块,这样就可以非常有效地减少了需要加载的默认动作数,并且会极大地提升首屏渲染速度,以上就是大致的 H5 端的渲染逻辑。

而对于 Weex 而言,则会是非常不同的一套逻辑。之前的分享里面有谈到在天猫里面做了首屏的拦截,在触发底部的 loadmore 事件的时候,会将所有的非首屏模块一次性地加载到页面上,而在淘宝这边所采用的的策略则是与天猫不太一样的。因为用户期望在首屏点击电梯跳转到页面指定位置的时候,需要将该位置的所有可视区域内的模块全部展示出来。在 Weex 中的渲染策略依然是首屏全部渲染完成之后,对于非首屏模块的进行一次性地加载。而这个一次性加载也分为了两个部分,首先是将能够直接拿到数据的斑马模块一次性地进行渲染,比如图中的 Module3、Module4 等,在这个过程中,如果遇到某个模块的数据需要自己请求或者需要额外的一些请求逻辑的话,这个模块会被等待掉。等待的时间大概会有几百毫秒,我们之前测试的数据是在比较低端的安卓机器上面大概需要八百毫秒左右,这种情况下,在一些比较不好的机型也不会产生太差的体验的。最终对于用户而言,可以非常快速地看到首屏,即使是飞快地向下滚动也能看到所有的模块都已经出现了,但是这样做的同时就是需要前端同学与自己的后端同学进行约定和配合,将页面加载的性能与服务器进行权衡,这就是 Weex 页面在双促中的渲染逻辑。

637760e66a5a8cb00355d3524f2227a747eff923

4.页面内元素的组织
接下来分享页面内元素的组织。我们与斑马进行对接或者在应用已经有了渲染逻辑的情况下,接下来进行一些模块的开发可能就需要有一些更加细粒度的元素。而对于模块开发者的影响可能就是需要使用 React。

下图是一个双十一的长列表模块的最简单的代码示例,在静态属性里面定义了很多自己模块需要的东西,比方说 getModuleRowHeight() 方法返回了一个经过计算后的模块的真实高度,有了这样的一个真实高度以后就能够在打开真实页面的时候将整个页面撑开。还有很多相关的约定的东西加上我们开发者习惯的 React 的写法就使得很容易进行 RAX 开发。

fe2277e75c413bff26370fa5f884cf1ab57d69c6

讲到标签和组件,还是需要拿刚才的那个例子来说明。最上面的 Header:精选好店、腔调好店等这些东西其实是由最基础的最细粒度的 Weex 标签提供的,Weex 里面的 div、scroller 以及文本图片这样的东西组成下拉的电梯,这样的组件经过 RAXUI 的封装会变成tabheader 提供给使用者。

6a4471188b47f67e04a59485797c15ca759e4d31

类似的 RAX 标签在整个双促中的应用是很多的,比如像弹窗、底部的 bar、布局以及倒计时、icon 等等,不过目前开源的版本包含的组件还是比较少的,未来将会有更多的组件经过双促的磨练之后会陆续地开放出来。

页面中已经有了很多细粒度的标签,通过这些细粒度的标签可以很容易地开发出业务的模块。像图中这样的比如是一个会场的页面,上部是 slider 的图像滑动,然后使用 tabheader 做电梯可以跳转到指定位置,然后最下边是一个长列表,这样的整个页面方案其实是用自己的一套组件可以进行实现的,以至于对于不同的业务场景,作为横向的 tab 滑动功能以及视频播放功能或者通过 tabbar 导航切换长列表,都是在现有的组件体系中完成的。

63e1a86b38231d45df39f09476d032532970b75f

接下来分享组件与双促中经常使用的模块之间的关系。tabheader 是用来实现所有的电梯以及底部的 bar 等有关 tab 切换的功能的;slider 可以用来做轮播;使用 grid 可以实现多列布局等等。

a37d917004eaaa2a758e42d1ca73662fdcc306af

在整个大促的过程中,有了这一层最基本的标签,通用的 RAXUI 的组件,我们在实现大促里面所需要的模块的时候其实只是进行了简单的业务封装。而双十一和双十二促销的时候就是需要在此基础之上对组件进行优化。比如对于 grid,之前为了减少嵌套,为了实现多列布局时会在一个容器中放置几个 View 实现多列,在双促里面需要标签嵌套的层级不能过多,为了达到这样的效果,其实需要将中间的层级去掉,使用 cell 的方式进行实现。再比如 picture,在 Weex 里面,是不需要关心图片的懒加载的,但是在 H5 里面直接使用原生的标签可能会出现很多问题。picture 里面做了很多事情,其中一个是基于滚动容器的事件封装,就是在滚动的过程中去加载图片数据,这样整个数据量在图片方面的减小也是非常可观的。对于视频播放而言,在 Weex 中有 video 标签专门负责,但是其提供的能力非常有限,所以需要一套更为通用的方案来兼容 Weex 和 H5,player 标签就是进行了更重一级的封装。有了这样的一套组件,就能够更加方便地实现双促的模块。


接下来分享一个在双促中为淘宝带来很大性能受益的例子。下图中最左边的那条线是包含两三百个坑位的长列表,放大后就是右边的一行两列的长列表的图,这样的长列表是由 List 和 cell 来实现的。为了使得这样的一个无限的长列表有更好的加载顺序,首先采用的方案是让自己的 Block 滚动容器使用 List 标签,里面的每一个模块、每一行都是用 cell 标签,但是在像斑马或者一些搭建的应用中很容易写一个外层的 div,里面包含了10行数据。这样的事情放在 List 列表中其实是没有进行细粒度拆分的,所以不会在处于非可视区域时进行回收。因此这样的情况在淘宝如此长的列表场景下是无法接受的,所以我们做的一件事情就是使得这样的页面可以被细粒度地进行拆分。

92c449c02395ffdf400133bf234160aac10a533f

最后分享一个刚刚在代码段中看到的 repeat 类型的模块,repeat 类型的模块所表示的是当前这个模块可以被重复地渲染很多次,而且每一行都是一模一样的,可以将类似这样的模块,每一行都单独进行拆分来实现更好的渲染。整个的渲染逻辑是:在开始时,渲染容器是一个空的 cell,这个空的cell是高度真实撑开,所以可以方便与电梯跳转到真实位置。当 cell 经过电梯跳转到可视区域的时候,会触发自己的 appear 事件,此时 appear 事件将会触发真实的数据并获取到请求回来,这样数据拿到之后将会通知给上一层也就是页面渲染层。对于页面渲染层而言,我们刚刚讲到了有做页面通信的东西,之后会将这一部分数据拿给页面上层进行拆分,上层将每条数据拆分成单独模块,做成 cell。这样,在整个页面加载的过程中,被回收的效果是非常明显的。

ad82a4ee046756914a48c427366661c6a001b3ad

在 H5 上的秒开则是不去加载坑位上的内容,而使用空占位容器实现的。在 Weex 上实现秒开也是一样的,但是在滚动的过程中,Weex 页面使用 repeat 类型的模块来做的,所以可以很有效地将渲染进行优化。还有刚才看到的页面所遇到的问题是如此长的页面肯定不能一下子渲染出来,所以在渲染时是以5行或者10行为单位实现的无限下拉,这样的无限下拉对应到模块上也是使用 appear 的机制实现的。这里补充一个概念,刚才提到使用电梯可以跳转到任何一楼层,因为可能是无限渲染的楼层,所以此时就不能够使用List原生的 loadmore 来做长列表的无限加载,就需要使用其他策略。而这个策略就是在最后一行数据 appear 的时机,监听当前页面的滚动容器滚动到了什么样的位置,在这样的位置上可以触发下次加载以获取更多的数据,之后再通知到上层的配置渲染层来达到整个楼层的无限下拉渲染。淘宝这样的渲染逻辑可能与天猫不完全相同,但是也是经历双促考验的有效的解决方案。总结下来就是 H5 下占位容器逻辑可以减少页面的节点,渲染时占位容器将拆分为多行模块。单个 repeat 模块分段加载,以5行进行分段,最后一行模块的 appear 事件实现无限加载。

其实除了大促之外,还有很多淘宝的业务,包括商家、搜索以及周围的业务都在使用RAX 。而且 RAX 目前已经开源了,它也是一套比较成熟的方案,大家感兴趣的可以访问 RAX 的 Github 了解更多信息( https://github.com/alibaba/rax)。

相关文章
|
6月前
|
JavaScript Java 测试技术
基于微信小程序的宠物店商城的设计与实现(源码+lw+部署文档+讲解等)
基于微信小程序的宠物店商城的设计与实现(源码+lw+部署文档+讲解等)
|
6月前
|
JavaScript Java 测试技术
基于微信小程序的手机商城的设计与实现(源码+lw+部署文档+讲解等)
基于微信小程序的手机商城的设计与实现(源码+lw+部署文档+讲解等)
|
6月前
|
JavaScript Java 测试技术
基于微信小程序的中国各地美食推荐平台的设计与实现(源码+lw+部署文档+讲解等)
基于微信小程序的中国各地美食推荐平台的设计与实现(源码+lw+部署文档+讲解等)
|
6月前
|
Web App开发 监控 前端开发
如何优化淘宝直播 PC 推流端性能(下)
如何优化淘宝直播 PC 推流端性能(下)
211 3
|
6月前
|
缓存 前端开发 JavaScript
如何优化淘宝直播 PC 推流端性能(上)
如何优化淘宝直播 PC 推流端性能(上)
316 2
|
监控 Serverless 持续交付
小试牛刀,一键部署电商商城
SAE 仅需一键,极速部署一个微服务电商商城,体验 Serverless 带给您的全托管体验,一起来部署吧!
2501 44
|
存储 消息中间件 运维
淘宝应用架构
淘宝应用架构
淘宝闲鱼京东等电商api的简单调用
淘宝闲鱼京东等电商api的简单调用