BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

BlendUI,让webapp的体验和交互得到质的提升

| 作者 雷志兴 关注 0 他的粉丝 发布于 2014年7月16日. 估计阅读时间: 17 分钟 | GMTC大前端的下一站,PWA、Web框架、Node等最新最热的大前端话题邀你一起共同探讨。

故事背景

百度轻应用已经推出半年多了,在市场上已有一定的影响力。但同时我们发现,开发者之所以使用轻应用,看中的是百度的渠道分发能力,而在体验上和Native app有比较大的差异,这个问题在应用复杂以后变得尤为明显。

前些年,在做移动web站点时,我们都会追求一些无刷新的跳转、换页效果,但后来发现这样做在市场顶级的手机上尚不能运行流畅,就更不用说那些相对廉价和低端的智能机了。所以近一年来,大家倾向于不在移动web站点中采用复杂的特效,只在最关键的部分,用最小的代价来实现。

现在你已经很少在Android中看到用Javascript实现的换页效果了;又比如百度的多数产品线放弃了Javascript实现的局部滚动效果,转而采用原生滚动实现,或者只应用到页面的少数交互元素中。与此同时,很多公司已经将重点精力投入到Native原生应用的开发中,减缓了在web端的投入。

而对我们,当然希望轻应用的体验和交互能够和Native媲美,那我们要做什么才能达到这个目标呢?做什么才是最有效的呢?

调研

我们首先看到了w3c的(一份报告),这是来自缩短与本地应用差距(closing the gap with native) 的任务组产出。这份报告指出了webapp相对Native app的优势与劣势。

我们接着寻找了很多份数据,概括得最好、数据量也很丰富的是Developer Economics的这份调研数据详细说说其中两组关键的数据:

  1. 为什么开发者不使用HTML5技术开发应用?
  2. 多少Native app可以用web技术实现?

经过对6000+开发者的调查,他们发现,46%的开发者认为性能是影响他们选择的因素,这也是在所有因素中占比最高的,其次是API的缺乏,占37%,再次是与Native元素的整合,占29%。这和做为移动开发者的我们的主观感受相当一致,性能是Webapp的巨大瓶颈,不流畅的app一定不受用户喜欢;其次是一些功能无法用web实现,比如语音、定位等;再次,即使这些功能可以用Native原生代码实现,也无法将他们整合到Webapp中。

而第二个问题是第一个问题的延展:抛开性能问题,webapp的能力和Native app相比有多大差距呢?他们调研了Google Play中的30339个app。如果只使用HTML5技术,能实现37%的app,如果使用Phonegap,能实现49%,如果使用Appcelerator,能实现63%。这个结果让人觉得很乐观,只要我们能用一些技术,将设备的一些基础功能开放到web中,能大幅提高webapp的应用范围。

与此同时,我们调研了百度内部的16款webapp,希望了解做为国内一线厂商的工程师,他们认为webapp的瓶颈所在。结论出奇的简单和一致,有87.5%的工程师认为,在自己的业务场景中,转场和动画问题是最首要的问题

其实移动web站点经过这些年的发展(我在2010年就参与过百度内部移动前端基础库的研发工作),工程师和产品经理已经很清晰地认识到什么交互是web无法实现的,比如3D转屏,动态的卡片式操作,他们会灵活地调整产品设计,避免这些交互。

但有一点是无法避开的,那就是页面的转场动画。web是基于链接构建的,从一个页面点击链接跳转到另一个页面,如果通过有刷新的打开方式,用户要面对一个空白的页面等待,如果通过无刷新的方式,用Javascript移入DOM节点,在Demo状态下能做得很好,但一旦产品化,就要冒着很高的性能风险:页面太大,可能转场不流畅甚至浏览器crash;单个webview中DOM节点过多,同时还要保存多个场景的状态,会占用过多内存,在使用的过程中会变得越来越卡;更不用提那些低端机型和低端浏览器了……

所以,我们面临的首要目标是,如何能webapp的转场能像Native那般流畅

实现思路

在说实现思路之前,要先给大家说说轻应用的业务场景,以便理解。

轻应用的业务场景

轻应用有两大入口:移动搜索和百度搜索app,接入轻应用的开发者他们最为看重的就是这个入口,尤其看重百度搜索app的入口。因为在普通浏览器中,通过移动搜索到达轻应用,这跟普通的webapp没有本质区别;而在百度搜索app中,由于轻应用的运行环境是百度框,我们能为轻应用的开发者暴露一些Native API的接口,这就是Clouda API,包括提供设备能力的Device API,提供百度云服务能力的MBASS API。

技术选型

由于轻应用的使用场景天然和Native结合得很好,我们很自然地想到利用Native技术来做转场。相对用web技术,这条路更为现实:市面上有很多转场相关的Javascript库,百度内部也有若干实现,但最后产品化以后是否成功,完全取决于具体业务开发者。开发者能否有效地缩减DOM数量和层次,能否找到性价比较高的方案是关键。而轻应用开发者的水平良莠不齐,用web技术来解决此问题显然不可行。

而用Native技术来做转场,我们也经历了一些波折。最初,我们重点考虑的是类似Appcelerator的方案,不过我们不像Appcelerator那么激进地将Javascript编译成Native code,而希望暴露一组基本的Native API,供前端工程师调用以实现流畅的app效果。但这样随之而来的问题是,开发者的可定制性会变得特别差,极其依赖Native API,而且开发感受也会很糟糕,毕竟他操作的不再是DOM,而是一个Java like的东西。这个方案很快被我们否定。

根据前面所说的调研,我很快发现其实大家对普通的web元素,并没有太多性能方面的担忧。不管页面多复杂,很少有会担心页面内部的性能,而担忧统统来自跨页面的转场效果。因此,我提出了一个概念:**Every element can be a webview**.

Every element can be a webview

从逻辑上来看,webapp是由多个view组成,而每个view又由多个Element组成。但在原生的web技术中,没有View这个概念,我们只能利用Javascript,将View用Element实现,这样,一个webapp中就有超大量的DOM节点。在view切换时,需要进行大量的重绘,性能就差了,在移动设备上表现尤为明显。

而BlendUI的这个概念让View有了「原生」支持,任何的Element都可以用一个独立的webview来实现,浏览内核的负担就减轻了,而且切换时的过场动画用原生代码实现,也保证了性能。

举个例子,这是已经采用BlendUI上线的百度阅读app,采用BlendUI来实现的话,原来是单页的webapp将分成很多不同的webview。

在首页,背后是一个webview,只用来显示头部,而底部由多个webview组成,以实现流畅的滑动效果。

打开图书页以后,覆盖在上面的是一个新的webview。

甚至可以将某个复杂的控件做成一个独立的webview或者由Native控件实现。

也就是说,页面中任何一个独立出现的元素,都可以用一个独立的webview来实现。简单一个概念,解决了三大问题:

  1. 转场不再卡顿。从我们事后的实测数据来看,FPS提高了一倍,从30 fps提高到60fps。
  2. 随处都可以使用原生滚动,因为我们可以将卡头卡尾的页面区域用独立的webview实现
  3. 单个web页的DOM节点数减少,从而使页面本身的性能大幅提高

最后的结果证明,这条路用极小的成本解决了关键问题。

在我们开发出了Demo后,Basecamp的工程师发了一篇博客,他里面有两个核心观点:

  1. Decisions based on computing speeds quickly decay. 硬件制约是一时的,语言和平台的生命力才最重要。
  2. Native shell + native navigation. 这是Hybrid app的一个简单但重要的改进,他们把Native code用在了对性能最为有利的部分。

最终,basecamp的这个版本大受好评,37singals只投入了1-2个工程师和半个设计师。他们的思路竟与我们出奇地一致。

核心实现

因为把握住了问题的核心,所以BlendUI的核心实现特别简单,向其他人解释这个问题也特别容易。我不用BlendUI有多少原生接口和能力这样的数据吓唬人,也不用长篇大论地解释内部有多么复杂的实现,只要演示我们的Demo,然后告诉听众,我们解决了页面转场和卡头卡尾的问题就可以了。

设计原则

我们秉承的设计原则有三条:模型从简;事件驱动;为开发者保留最大的灵活性

  • 模型从简,这条原则贯穿始终。一句话来说,BlendUI让Javascript拥有了控制webview的能力。
  • 事件驱动,这也是Javascript的核心。跨webview通讯、Javascript和Native code通讯,几乎全是事件。
  • 为开发者保留最大的灵活性。这意味着BlendUI不会影响开发者对其他库、框架的选择,更不会在UI风格上面有任何限制,所有的东西都是Web的,定制性无限。

系统概览

系统亦很简单,分成上下两层。下层(蓝色部分)由Native code实现,上层(绿色部分)由web实现,下层提供核心能力,上层完成封装。

核心能力包括两部分,Runtime和BlendUI。前者是轻组件的运行环境,插件机制是它的核心,设备能力、BlendUI都是插件,这样能最大限度地减少SDK的体积(极限状态下100多K),所有插件都可以动态联网下载和更新。BlendUI的核心自然是其Webview控制力,除此之外还包括扩展BlendUI的Native组件的能力,这和Runtime的插件机制类似,它能通过Javascript调用动态地加载外挂的组件。

在上层封装中,我们除了封装iOS和Android两个平台的能力,提供统一的API之外,还提供了一套退化的web实现,这样我们能让基于BlendUI开发的应用在普通浏览器下也能正常运行。

关键概念

Layer和LayerGroup是BlendUI两个关键概念,Layer即webview,LayerGroup即一组webview的集合。Layer可以通过Javascript设定其显示的位置和大小,也可以指定滑入时的动画;LayerGroup实现了最典型的组合,通过滑动切换不同的Layer。

要让某元素固定在可视区域的某位置,比如顶部的Tab切换条,用一个独立的Layer实现Tab,并固定其位置和大小即可:

new Layer({
    url: "/path/to/tab.html",
    top: 0,
    left: 0,
    height: 30px
})

剩余的区域用一个LayerGroup实现:

new LayerGroup({
    url: "/path/to/content.html",
    top: 30,
    left: 0,
    layers: [
        {
            url: "/path/to/content1.html"
        },{
            url: "/path/to/content2.html"
        },
    ]
})

事实上,这些Javascript API都是通过调用Native植入window上下文的window.lc_bridge方法来实现的。

此外,通过监听BlendUI提供的事件,就可以实现内容切换时,Tab页高亮区域转变的效果:

document.addEventListener('groupScrolled', function(index){
    highlightSwitch(index); 
});

我们很快也会提供ListView Header类似的滑动卡头的能力。

除了Layer和LayerGroup,就是原生组件的嵌入了。

new Slider({
    "images" : [
        {
            url: "/path/to/photo1.jpg"
        } , {
            url: "/path/to/photo2.jpg"
        }
    ]
})

前文已经提到,原生组件是动态选择和加载的,这部分封装其实调用了 window.lc_bridge.addComponent("com.baidu.blendui.component.slider"),addComponent方法会去动态地加载Slider,并且调用其中的execute方法。

适用场景

这项技术,首先对轻应用开发者来说是巨大的福音。在不接触任何Native代码的前提下,就能让轻应用的体验有质的提高,这项技术将很快通过轻应用Runtime下发到所有轻应用的运行环境中。一旦BlendUI集成到百度搜索app中,直接在app中打开的轻应用,这样既能使用百度的分发渠道,也能有较好的浏览体验。

另外,BlendUI很适合大app中的独立频道单独发布app上架(比如豆瓣那一大堆子频道),既能节省人力成本,能保证基本的用户体验,又有很高的定制性,迭代速度和web相当。这样就能快速试错,即使产品决策失误,开发成本也不高,也容易调整 —— 这是互联网产品的核心优势。

作者专栏

行云出岫

 

云无心以出岫,鸟倦飞而知还。希望能给你带来一点灵感。


感谢王保平对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

又在画饼了,只开源一半,有啥意思,鸡肋 by zhou jony

说的这么好,打包平台什么时候对外开放,还是只画过饼

Re: 又在画饼了,只开源一半,有啥意思,鸡肋 by berg Lei

八月初开放

大公司有钱烧的 by 变 大象

大公司有钱烧的,这个blendUI就是半拉子bacbone加半拉子phonegap,关键是什么都需要自己实现,专业开源产品有很多插件可供选择

扯了这么多 by 曦 杨

扯了这么多我就看到一句话“又比如百度的多数产品线放弃了Javascript实现的局部滚动效果,转而采用原生滚动实现” ,在半年前我在写一个针对百度云盘的js小工具的时候就发现百度云盘的滚动条是假的,是一个div,通过ajax模拟滚动效果,我当时就在想:做的这么装逼,云盘ui的程序员得多苦逼啊,出了bug得有多难改啊。半年之后发现百度云盘默默的把滚动条改成原生的了。我不得不说,这就是公司大了吃饱撑着没事干,得搞点逼格的事情出来增加工作量。

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

4 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT