CodeHub#7 正式落幕,来自蚂蚁集团的技能专家「京君」与社区的开发者们共享了「支付宝」全新的卡片技能栈——魔方卡片(Cube)。
京君环绕 Cube 技能的架构逻辑,阐述其烘托和生产进程,并辅导开发者完成初阶的技能调试。
▶点击播放,可观看 CodeHub#7 完好回放;公众号mPaaS后台回复“Cube”可获取讲师完好PPT。
动态卡片的背景
从 Windows 年代开端,运用程序图标就成了用户(流量)的主进口,而且一直继续到移动端年代。图标即进口的方式,缺陷是不直观,最少需求一次点击后才干接触到想要的信息。在此背景下,iOS体系和部分Android体系完成了把内容和服务前置的卡片,如下图所示:
此外,鸿蒙体系也提出了类似的卡片场景,作为某种流量进口。实际上,在运用内部的卡片作为内容展现以及服务进口的场景则更为普遍,比如支付宝主页和招行银行的理财页面,其间每个小矩形都是一个卡片。关于运营来说,卡片款式和内容能够随时装备,不必等候运用版别升级,也是某种刚需。
魔方卡片(Cube)概要
**魔方卡片(Cube)**是蚂蚁集团内部自研的一套跨渠道动态化卡片解决方案,是服务于运用页面内的区域动态化技能,面向内容运营,协助产品技能进步开发功率和运营功率。每一个魔方卡片(Cube)独立嵌在原生页面内的一个区域,区域内容经过卡片模版进行展现。
这儿展开讲下高功能。魔方卡片(Cube)寻求的是挨近native原生体会。咱们界说了两个维度:
一个是极致的功能。在Cube小程序才能的基础上,咱们去掉了一些杂乱的css才能,例如伪类伪元素、inline/block等,一起也对js的才能做了约束(魔方卡片运用quickjs作为脚本引擎)。此外,咱们还对quickjs做了一些优化,包含不限于离线atom编译优化,异步gc优化等。咱们也引进了wamr作为quickjs的“协处理器”,支撑用户运用javascript和assemblyscript混合开发。这样用户能够用assemblyscript一些热门函数或许模块。
另一个维度是极致的内存。在信息瀑布场景无限下拉,魔方卡片的内存增长挨近Native卡片。咱们对卡片的才能做了比较精密分级,经过在开发时装备,减小运转时的内存耗费。下图展现了一个简略卡片,如图所示魔方卡片的工程目录,以及钱包某个卡片的真实代码和运转作用。
Cube卡片的生产&作业流程
-
研制期
-
- 本地开发
魔方卡片(Cube)配套独立的开发工具,支撑卡片的编译、日志输出、实时预览等功能,vue作为当时开发模版的dsl言语,支撑js、css修改卡片款式。
-
- 卡片办理
卡片本地开发完成后,经过卡片办理后台将卡片编译产品上传发布,能够对卡片进行版别办理,卡片发布后就能够在客户端进行卡片的动态更新。
- 运转期
为了便利端上事务接入魔方卡片,咱们引进了一个魔方卡片容器(CardSDK)的概念。CardSDK把一些和事务层/服务端联系紧密的,且通用才能做了一些封装。例如咱们经过CubeCardSdk从服务端拉取卡片和事务数据。此外CardSDK也负责常用的JSAPI、第三方组件的接入。这样魔方卡片能够更专心于卡片产品自身。
核心体系架构
魔方卡片(Cube)的体系架构首要包含JSEngine、CardEngine、RenderEngine和Platform几部分,绝大部分代码都是C++完成。
- JSEngine
首要负责卡片js逻辑履行和卡片数据改变监听,从而支撑开发者在卡片内部写一些事务逻辑才能完成卡片内容和款式的动态改变。
由于卡片场景对功能要求较高,综合包大小和功能等方面考虑,咱们挑选了quickjs作为咱们的js基础引擎库,一起完成了一个十分小的js呼应式框架(JSFM),用来支撑卡片内的逻辑代码才能。
- CardEngine
首要负责卡片数据的解析和绑定、卡片逻辑烘托、构建DOM指令、JSAPI办理、JSBinding、Native事情通讯等。
卡片DOM树的初始化构建进程,咱们并没有把它放在js运转时,而是在卡片实例初始化链路中直接经过C++进行指令生成和树构建,一方面是为了坚持js框架更小更快,另一方面C++的运转功率更高。
- RenderEngine
后端烘托底座,负责卡片布局核算、款式解析、Layer核算、自制作组件、同层烘托、光栅化上屏等进程,以及手势、动效等交互作用。
- Platform
渠道相关接口,包含原子view封装、Canvas API、三方组件扩展协议、动画api等。
线程模型和数据模型
线程模型
魔方卡片(Cube)生命周期内的首要线程包含事务线程和引擎线程,事务线程是卡片数据的初始化阶段由事务发起履行,是卡片生命周期的beforeCreate阶段。引擎线程是所有卡片生命周期运转阶段的共有线程,首要包含Bridge线程、Render线程、Paint线程和UI主线程。
- Bridge线程
js运转时线程,也是Dom节点数据查询和处理线程,由于依据魔方卡片小、快的定位,js逻辑只是卡片一个辅助才能,不具备过于杂乱事务逻辑才能,所以Bridge线程相对较轻,并规划为单线程形式。
- Render线程
烘托相关数据核算线程,包含烘托树构建、节点层级核算、Layer分层制作核算、手势数据核算以及烘托使命构建,Render进程首要触及树的递归核算进程,相对烘托进程耗时很短, 规划为单线程形式。
- Paint线程
制作线程,履行卡片节点分层制作及光栅化使命。Paint线程并不是一个固定的线程,依据当时使命模型,Paint线程可能是主线程,也可能是一个线程池里的子线程;在同步烘托形式下,Paint线程直接是主线程;而在异步烘托形式下,经过一个线程池来完成Paint使命的并发烘托,进步烘托功率,例如在列表滑动场景。
- UI主线程
UI操作主线程,即为现在的渠道线程,首要包含手势辨认、UI上屏和三方扩展组件的数据更新等。
除了以上触及的首要线程外,还有埋点和监控相关的playground后台线程,全体优先级比较低。全体的线程模型规划,最大极限减少UI主线程压力,进步卡片并发烘托功率。但现在还有一些缺乏,包含UI线程切换频繁、Bridge线程越来越重等,后面会继续优化线程模型。
数据模型
和线程模型对应的数据模型首要包含三棵树:NodeTree、RenderTree、LayerTree,除此之外,还存在一个暂时的PaintTree;
- NodeTree
卡片原始节点树,对应前端的Dom树,引擎会依据NodeTree做款式解析和布局核算;
- RenderTree
烘托数据树,这是一颗变形树,许多情况下它的树层级结构和NodeTree是相同的,其实当初在规划界说引擎数据模型的时分,咱们讨论过究竟要不要这棵树,有没有必要存在这样一颗和NodeTree层级相同的树,最终咱们仍是保留了,原因是这棵树能够比较灵活的调整树关系,假如把卡片分为布局阶段和烘托阶段,那么这颗树便是烘托阶段的源树。
事实证明咱们的决定是正确的, 咱们后续支撑的zindex/static等才能,都是由于这棵树的存在能够在引擎层很好的去支撑, 而不必在渠道层去模拟完成这种层级改变才能从而导致很有限的场景支撑,包含今后咱们做烘托快照技能也能够从这颗树去考虑。
- LayerTree
LayerTree树,顾名思义便是一个分层树,在RenderTree基础上对节点进行分层,同一层的节点在同一个烘托使命管线内做制作光栅化,不同层之间相互独立,能够并发烘托。
- PaintTree
PaintTree是一个暂时树,其实严格的说是一个复制树,是经过RenderTree复制一个子树,每次产生烘托时暂时生成,当然也会做些节点优化处理,例如被彻底盖住的节点会被优化调,防止重复烘托。每一个layer上存在一个PaintTree,经过PaintTree进行节点制作生成光栅化指令或位图。
高功能列表烘托
关于列表内运用卡片的场景,首要考虑的是卡顿影响,尤其是中低端机设备。魔方卡片(Cube)支撑异步烘托,所以在列表场景下能够很流畅,一起由于支撑多线程并发才能,能够多张卡片并发烘托,所以在异步烘托条件下也不会有显着的白屏作用。
Native技能优化
咱们期望卡片服务于页面内区域化内容动态展现和简略事务逻辑,更多的是面向移动端开发者。即便咱们运用的卡片DSL言语描述是前端言语,咱们也期望能够对CSS的运用做约束、支撑有限的CSS才能,但一起也期望尽可能掩盖到一些开发者常用的CSS才能。
所以咱们针对CSS才能做了一个专项作业,和前端团队技能同学一起做了魔方卡片(Cube)CSS才能标准,对CSS才能做了约束约束。即便如此,在Native烘托引擎下,想十分好的去支撑这些才能,也是有许多困难,包含zindex的支撑、overflow等,因而咱们也依据一些依靠的渠道才能也做了优化处理。
Layer容器
咱们引进Layer容器概念,前面介绍数据模型时,提到了LayerTree,每一个Layer节点是一个独立的烘托容器,由渠道View作为Layer容器来烘托其他虚拟节点。假如依照常规的做法是一个View对应一个烘托容器,咱们运用两个View组合为Layer容器(iOS运用CALayer),将内容层和逻辑层别离,这样做的好处许多,例如layer节点的shadow制作约束裁剪问题、内容层的画布切开优化等。
手势改造
手势的优化改造首要为了解决渠道体系手势分发才能的约束,不管是Android渠道仍是iOS渠道,体系对手势的分发处理都有一些约束,例如兄弟节点不能分发事情(iOS)、超越父节点区域无法接纳事情(影响overflow才能)等,所以需求对手势进行改造。
由于卡片烘托支撑三方组件扩展,为了不影响扩展组件的事情呼应,咱们依据Layer容器接收改造体系手势行为,内部进行容器节点的手势分发办理,而关于存在三方组件混合烘托的场景,Layer容器和三方组件之间的手势分发坚持体系行为。
光栅化
魔方卡片(Cube)烘托进程包含指令烘托和位图烘托两种烘托形式,这两种形式会在不同场景条件下切换,用来优化不同场景下功能,例如帧率和内存。位图烘托在Android上相对比较杂乱。默许是用Bitmap作为离线烘托的缓存,缺陷是引进一次额定cpu/gpu内存复制而且无法充分利用GPU资源,优势是兼容性好。咱们尝试过运用textureview作为离线烘托缓冲,发现6.0以下设备存在严重的兼容性问题,而且不同设备之间的稳定性不同巨大。
一起光栅化才能依靠渠道体系的Canvas API,有些高阶方法会触及硬件加速的约束,包含shadow api以及体系对glRender buffer的约束(Android渠道),咱们也对大画布场景做了视图切开分段烘托来确保烘托功能。咱们一起也在着手用Skia Canvas api替代渠道层的Canvas API。
同层烘托
魔方卡片(Cube)把三方组件当作独立一层layer独自进行数据更新,能够十分便利高效的接入扩展的三方组件。依据体系的UI才能,使扩展组件在卡片内天然生成统一烘托。一起支撑组件在不同卡片上的复用。在实际的事务场景中,同层烘托也带来了许多额定的问题。比如地图/视频/动画等组件,一般会伴随着较大的功能内存开销。这些开销对卡片的烘托会有负面影响,尤其在列表滚动时。关于地图/视频组件,咱们配合组件提供方case by case的解决问题,而且试图在卡片上线时设置卡点。关于动画组件,Cube继续的在扩展特点动画/帧动画才能,而且内置canvas才能。
魔方卡片(Cube)的现状和规划
现在魔方卡片(Cube)已经服务「支付宝」的主页、证券(股票)、卡包、出行等20+的事务场景,日pv超越100亿。在未来适当长的一段时间内,「支付宝」内部的事务场景,将逐渐把存量的native卡片和h5卡片Cube化。
因而,咱们一方面会继续把开发者体会做好,比如开发调试工具链条;另一方面咱们也将继续的优化基础功能,比如寻求更小的包体积,更低的内存等。
一起,魔方卡片(Cube)Beta 已上线 mPaaS 供广大移动开发者运用,公测期间,登录 mPaaS 控制台,立即赠送十个卡片模版免费运用。> > 点击这儿 < <体会魔方卡片。
卡片未来规划的另一个方向是物联网设备(例如RTOS)的运用开发栈。准确说不是魔方卡片,而是卡片和小程序的某种中间形状。
物联网设备的界面一般比较简略,近似卡片;但是又需求多个“卡片”之间的路由才能,更挨近于运用的形状。这样一个混合形状既能保留魔方卡片(Cube)在内存/功能/包体积上的优势,又能满足物联网设备运用开发的诉求。
依据咱们的调研,大部分RTOS运用开发环境仍是停留在传统的C言语,效能和动态性都不抱负。因而关于开发者来说,Cube 也许是一个不错的挑选。
引荐阅读:《Cube 技能解读 | 支付宝新一代动态化技能架构与选型总述》
> > 点击这儿 < <体会魔方卡片。