LuaView高性能、动态化、跨平台应用开发引擎—聚划算动态化之路
EthRWC
9年前
<p> </p> <h2>1. 移动开发困局</h2> <p>业务快速发展的互联网产品,其移动应用往往会遇到版本迭代速度跟不上需求变更速度的问题。这时候让应用具有动态化能力就显得尤为重要。所谓的动态化是指应用不发版实现内容动态更新的能力,这里的应用内容不仅限于基本信息(如售卖的商品信息),而且涉及应用的主体框架、信息结构等深层信息(如页面整体排版、布局)。比如聚划算3.8大促,可能需要临时对线上活动进行一个大的调整,如果采用Native技术实现的话,正常的发版节奏显然无法支持这种变更,但如果应用具有动态化能力的话,就可以通过动态发布解决上面的问题。</p> <p>为了达到应用内容动态更新的目的,业内先后出现过很多动态化方案。有部分Native、部分Html5的混合架构Hybrid App,这种方案以H5的动态性为基础,通过定义Native的扩展(Bridge)来实现动态化;有约定数据结构,使用Native进行渲染的Native View方案,通过修改预定结构中的数据,实现动态化;有现在火热的ReactNative技术,通过JavaScript脚本引擎支持页面DOM转换和逻辑控制来实现动态化;还有开源界一大批小众的动态化方案。这些动态化方案都能一定程度上赋予APP动态化能力,但是每种方案都有其不太让人满意的缺陷以及能力瓶颈,如Hybrid的H5部分体验较差;Native View结构变化不够灵活,不支持逻辑的动态化;ReactNative 的JS引擎过重,不适合做长列表等。总之,尚未出现一种可以一统江湖的动态化方案。</p> <p>聚划算目前正处在业务高速增长的时期,业务需求应接不暇,中间还穿插各种需求变更,基本的发版节奏已经很难满足业务需求,而h5的体验又不能很好地支持业务,能否构建一套Native动态化方案就变得非常迫切。在这种情况下,聚划算开始了自己的动态化之路。</p> <p>在最初的时候,我们的工程师采用Native View方案构建了一套名为Box的简单动态化系统(如图)。通过预先约定好前后端Json数据格式和解析规则,在Android、iOS端以相同的方式解析、渲染服务端数据,从而实现两个端的简单动态化页面。Box能做到图片以及链接的动态配置与变更,但Box最主要的问题是只能下发结构预先定义的数据,并且不能下发处理逻辑,这就造成Box系统的适用范围非常有限,只能处理预定结构的服务端数据,无法构建复杂的UI,无法支持个性化Native页面。</p> <p><img src="https://simg.open-open.com/show/7a88be20c25875917a4d23132af800cd.png"></p> <p>为了更好地支持页面动态化,支持复杂UI,支持逻辑下发,我们又继续向更高级的方案出发,这就是接下来要介绍的方案—LuaView,说到LuaView,首先要从Lua语言说起。</p> <h2>2. Lua脚本语言新探索</h2> <p>Lua脚本语言的设计初衷是可以方便地嵌入到其他语言中,为应用程序提供灵活的扩展和定制功能,现实中的Lua更是不仅可以作为应用程序的扩展,还可以作为应用程序的配置文件。同时Lua脚本语言已经被广泛地用在各种场合以及应用程序中,游戏领域有大名顶顶的Minecraft、魔兽世界、愤怒的小鸟等;应用领域有Adobe Photoshop Lightroom。</p> <p>Lua脚本语言的内核非常小,官方Lua 5.0.2的内核只有不到120KB,这使得Lua脚本的启动非常迅速,在所有脚本引擎中,Lua是平均意义上最快的。在嵌入式和移动领域,体积小,启动快是一个极大的优势。此外,Lua脚本还有容易理解,易于维护等优势。</p> <p>Lua脚本语言有着极强的可扩展能力。虽然Lua并不象其它许多”大而全”的语言那样,包括很多功能,比如网络通讯、图形界面等,但是Lua提供了非常易于使用的扩展接口和机制,可以轻松通过宿主语言完成能力扩展。</p> <p>总之,Lua脚本语言具有可扩展性强、简单、高效、占用体积小、启动速度快等诸多优势,同时已经被业界使用多年,有着许多成功案例,是动态化方案首选。</p> <p>在聚划算中最普遍的动态化需求是开发一个活动页面,基础活动页面的开发需要两种能力,一种是逻辑处理能力,这个Lua本身已经具备,一种是UI视图构建能力,这个Android、iOS原生已经支持,高级活动页面的开发可能还需要原生系统的其他能力,如网络、存储、硬件控制等,这些Android、iOS原生系统也已经支持,因而我们的动态化方案核心就变成了如何将Android、iOS原生的UI、网络、存储、硬件控制等能力桥接到Lua层,有了这些能力,我们的动态化方案就可以支持UI动态搭建、脚本、资源、逻辑动态下发。借助Lua语言的可扩展性,我们可以很方便地在Native跟Lua之间搭建起桥梁,将Native的各种能力迁移到Lua层。</p> <h2>3. LuaView设计原则</h2> <p>在Native跟Lua交互的诸多能力中,以UI视图构建能力最为基础,因而我们将最终产出的动态化方案命名为LuaView,意为使用Lua构建Native UI。</p> <p>使用Lua脚本语言实现Android、iOS动态化,面临最大的一个挑战是:避免重新开发一套UI库的前提下,在Android、iOS系统之间构建一套统一的Lib库,并且保证两个端的Lua脚本代码一致,特性一致,做到Write Once Run Both。</p> <p>为了避免大动干戈开发一套UI库,我们选择借用两个平台的原生UI库。同时我们选择了现有的成熟的Lua引擎(LuaJ & LuaC),并稍作修改以适应移动端的需求,通过构建桥接平台,小心地设计Lua层API,最终做到了Write Once Run Both,并且上层API表现上也很自然。</p> <h3>3.1 LuaView SDK整体架构</h3> <p><img src="https://simg.open-open.com/show/242354dbddfbbf1bf257942f1265d1a5.png"></p> <p>如图,LuaView SDK的整体架构可以表示为五层。</p> <p>自下而上第一、二层依次是OS层和Framework层,分别表示了Android、iOS以及对应的框架层。</p> <p>紧接着是Lua虚拟机,在Android、iOS平台分别是LuaJ和LuaC,两个虚拟机都是目前两个语言中用的最广泛,最稳定的虚拟机。</p> <p>处在第三层的还有脚本管理模块以及安全控制模块,它们分别负责Lua本地脚本管理(包括脚本的解包、验证、加解密、解压缩等工作)和Lua脚本的安全校验工作(脚本完整性校验以及脚本安全校验等)。</p> <p>处在第四层的是LuaView的核心Lib库,包括两部分,一部分是Lua UI Lib,主要是所有的UI组件(如Button、Label、Image、TableView等);一部分是Lua Non-UI Lib,主要是所有非UI组件(如Http、Json、Audio等)。</p> <p>处在最上层的是Lua业务脚本代码以及Lua层的Lib库(方便第三方使用的Lua写的Lib库)。</p> <h3>3.2 LuaView两个重要设计原则。</h3> <p>Write Once Run Both:</p> <p>LuaView的一条重要设计原则就是同一份逻辑只写一份代码,这需要在设计SDK的时候尽可能得考虑到两个端的共性跟特性,将API构建在两个端的共性领域中,对于两端的特性领域则交由各自的Native部分来实现。目前LuaView SDK的Android端、iOS端已经完成输出统一的Lua接口,同时保证API特性一致,做到一份脚本两个端运行出来的效果一致。做到一份脚本跨Android、iOS平台运行。</p> <p><img src="https://simg.open-open.com/show/fb89bd5f0e8d8b879b325c2b0e54c7cb.png"></p> <p>Simple & Easy:</p> <p>LuaView的另一个设计原则是保持Lua语言的简单和易用。核心UI库上,所有的API做到精简,能够使用脚本实现的,尽量避免使用Native来实现。设计API的时候保证所有的LuaView 语言层使用Lua原生语法,所有的UI控件库接口跟Android、iOS保持一致风格,方便两个端开发人员的迁移。</p> <h2>4. LuaView动态能力</h2> <p>LuaView的动态能力基本上可以跟Html5匹敌,做到数据、资源、页面结构,甚至代码逻辑的动态下发,并且LuaView支持本地代码&资源缓存,可以有效降低每次加载的时间,减少不必要的服务器交互,提升页面加载速度。</p> <p>LuaView既可以作为完整页面,也可以作为某个视图组件使用(这是Html5很难做到的一点),同时还支持Native组件注入,很好地满足了完整APP,现有APP部分功能替换以及现有组件接入LuaView动态能力等场景。</p> <p><img src="https://simg.open-open.com/show/208363ba6f75824eabeda261f1c1f5b1.png"></p> <p>页面级场景:</p> <p>LuaView可以承载独立页面,一个页面的所有功能都使用Lua脚本开发,同时SDK提供了脚本&资源缓存,脚本下载&解包等功能,能够快速支持业务开发。新开发一个完整页面的情况下,非常适合此种场景。</p> <p>组件级别场景:</p> <p>LuaView可以作为独立的UI组件,嵌入到任何视图树中,同时该块UI组件可以跟Native交互,具备动态更新能力。对于页面已经开发完成,但某块成熟业务中某些内容需要频繁变更的时候,非常适合此种场景。</p> <p>Native组件注入场景:</p> <p>将一个应用原有的Native UI组件作为子UI注入到LuaView中,同时支持该Native UI组件调用Lua层代码,Lua代码也可以做到动态更新,从而实现Native UI组件功能的动态变更。对于页面已经开发完成,但某块UI处理逻辑需要动态变动的时候,非常适合此种场景。</p> <h2>5. LuaView现状&后续工作</h2> <p>LuaView目前已经在线上运行将近半年时间,支持了聚划算多个垂直业务,表现稳定。</p> <p>后续LuaView主要围绕以下三方面进行工作:</p> <p>1. API完善</p> <p>LuaView是构建在两个不同平台的统一框架,为了在Lua层屏蔽掉两个平台各自差异,需要我们持续完善我们的API设计,其中涉及到增加新的共性API,去除老的不兼容API,采用更优方式实现API统一等。</p> <p>2. 性能&结构优化</p> <p>LuaView毕竟是在已有的Native Framework框架上又搭建起来的新层,性能必然会有损耗,如何将这种损耗降低到最低,达到最优,是我们一直在做的事情。另外,为了更方便的支持上层业务开发,需要将Lua API以及结构梳理地更顺畅,进一步减少学习成本。</p> <p>3. 文档、Demo、支持工具丰富化</p> <p>LuaView尚处在发展前期,各种文档支持、Demo示例,以及支持工具都还不够完善,需要LuaView团队以及整个社区的支持。</p> <h2>6. 开源</h2> <p>为了更好地回馈社区,提升整个无线社区的开发效率,同时也让更多的人参与进来,借助社区的力量提升整个项目质量,让LuaView真正成为一个能够服务更多团队的框架。我们已经将LuaView项目整体开源,项目地址 <a href="/misc/goto?guid=4959009806265741975" rel="nofollow,noindex">https://github.com/alibaba/LuaViewSDK</a> 。</p> <p>目前我们开源的主要内容包括LuaView-iOS、LuaView-Android、LuaViewDebugger等。为了方便大家入手,我们还整理了所有的API,形成了APIDoc,供大家参阅。此外我们还有丰富的测试脚本,可以帮助大家快速入门。</p> <p>来自: <a href="/misc/goto?guid=4959672829025255593" rel="nofollow">infoq</a></p>