你尚未登录,仅允许查看本站部分内容。请登录使用邀请码注册
berg

BlendUI,让webapp的体验和交互得到质的提升 21个回复 专栏 @ 无线

berg 发布于 2 年前

故事背景

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

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

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

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

调研

我们首先看到了w3c的(一份报告)[http://www.w3.org/wiki/Closingthegapwithnative],这是来自缩短与本地应用差距(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组成,以实现流畅的滑动效果。

Alt text

Alt text

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

Alt text

甚至可以将某个复杂的控件做成一个独立的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的,定制性无限。

系统概览

Alt text

系统亦很简单,分成上下两层。下层(蓝色部分)由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相当。这样就能快速试错,即使产品决策失误,开发成本也不高,也容易调整 —— 这是互联网产品的核心优势。

  • raphealguo

    如果是根据这套API实现的webapp,可以单独在其他浏览器打开看到网页吗?
    如果不行,是否考虑实现一些类似BlendUI相关钩子的js库给第三方,以达到平稳退化的目的?

    #1
  • berg

    @raphealguo 可以的,我们做了一套平稳退化的库。我补充到原文中吧~

    #2
  • raphealguo

    @berg 你编辑文章也会发通知给评论者?好像有点怪怪的。

    #3
  • HJin

    这就是跨语言工程师的优势所在了。

    期待这套方案逐渐成熟并被广泛应用。

    #4
  • berg

    更新一下我们最近的进展:

    webapp到底还缺什么

    @markate 对国内的400+app(非游戏和工具类)做了调研,发现HTML5和Native app的鸿沟,可以进一步缩小。

    1. 能力。包括:离线能力、输入调起键盘、设备状态、系统控制、多媒体处理、文件系统、跨应用调用。
    2. 容器。这部分主要是流畅度的差距,包括可滑动的容器、可滑动的Tab、卡头效果、下拉刷新、无限滚屏。
    3. 组件。如分享、弹出层、划图浏览、IM、多级菜单、刮奖、摇一摇等。这也是流畅度的差距,不过和容器部分不同的是,容器内部需要大量自定义,而组件不用。

    Blend是一种理念

    就如同我在qconshanghai 2014中所说,Blend不仅仅是一项「拿来即用」的开源技术,更是一种开发理念。使用这个理念,app不仅能保留web灵活性,剔除冗长的版本发布过程,做到极快的迭代速度,还能在交互中保证足够的流畅性。

    事实上,国内外有很多app都使用了类似的技术。Instagram、Evernote、Apple app store、iBooks、Twitter,这些app的部分核心功能都是由webview渲染的,而国内的BAT开发的app:手机百度、手机淘宝、微信等,他们都有不少web实现的部分,尽管不是占其主要功能,但在app中起到了不可或缺的作用。如手机百度的搜索结果页,微信的公众账号,手机淘宝的专题等,这部分功能的核心在于灵活性,这也是web天然的优势。

    多webview技术

    从Blend一开始,就采用了这项技术,经过几个月的发展,多webview变得更灵活。webview能自由地放置在屏幕的任何位置,并拥有良好的入场出场动画。而我们对多webview的性能和内存开销也进行了控制,避免潜在的crash、卡死等问题。

    webview即容器,而这个容器是可以做得十分多样化的。如抽屉、左右滑动、弹出层等效果,都可以通过容器来完成动画,而内容仍然由web完成,这样可以真正释放web的灵活性到app中,让app达到与web相当的迭代速度。

    在使用多webview技术的时候,推荐大家使用Background page来做事件通讯的中枢和调用插件的入口。这样能让程序变得更加易维护,也能减少对Native资源的占用。跟DOM一样,webview也要慎用、及时销毁,否则仍然会碰到app资源不足的问题。

    常用或关键组件Native化

    如toolbar,导航等固定在屏幕特定位置,起到关键作用的组件,我们可以将这些组件替换成Native控件。不仅能让app体验更加流畅,并且可以在先于页面内容加载出来,提供更好的用户体验。

    这些组件可以不内置到Blend的Native SDK中,而是通过插件动态加载技术来加载,以缩小app的体积。

    Blend以后

    经过Blend理念的优化,同样用web技术开发的app,帧率能从30-40fps提高到55-60,和Native相近。这是因为Blend帮助app做了如下优化

    • DOM:极大缩减DOM体积,复用webview减少重绘
    • Javascript: 避免大量DOM Event监听
    • 动画:Android View 代替 CSS3
    • 网络:资源离线;webview预加载、预渲染
    • 复杂控件:嵌入Native控件
    • 内核:T5浏览器内核

    我们期望,使用了Blend理念后,app的性能、灵活性和能力都能得到保证。

    以后还能做什么

    我们会在十一月初开放Blend SDK,使用者可以嵌入这个SDK到自己的app中,以获得Blend提供的多webview和插件动态加载的能力。

    Blend对各种量级的开发者都有帮助。对于小开发者,使用Blend能快速开发出App的最小可执行产品,快速上线迭代,有任何问题都能随时调整;对于中大型开发者,使用Blend能释放web的灵活性到app中,保证体验的同时,又能做到随时更新。

    对于百度前段时间发布的直达号,我们也期待和直达号商户、代理商合作。Blend的能力会内置到百度系部分拥有巨大用户量的app中,直达号在这些app中将拥有更强的用户体验。而直达号商户不用修改任何代码,就可以基于直达号发布一个app,借助百度的app渠道让更多的用户直达商户。

    #5
  • gerald

    所以是native app要嵌入Blend SDK,然后在里面打开的webview才能使用blend ui这一套的js api,这样理解对吗?

    #6
  • 柒柒

    需要百度APP 的中间件才能用吧。要是能打包成独立APP就好了

    #7
  • berg

    @柒柒 可以打包的啊~

    #8
  • 柒柒

    @berg 有详细资料么=我比较笨找不到相关的资料

    #9
  • berg

    @柒柒 hybrid.baidu.com

    明天有新官网上线!

    #10
  • 柒柒

    @berg 目前没有本地打包方案么

    #11
  • berg

    @柒柒 clouda.baidu.com 这里有。

    #12
  • looping84

    @berg hybrid.baidu.com 404

    #13
  • qdsang

    @berg 只看到线上打包android,能打包成 IOS 应用吗? android环境有嵌入SDK的完整项目demo吗?

    #14
  • berg

    @looping84 hybrid.baidu.com/blendui 这个

    #15
  • berg
    #16
  • qdsang

    @berg 谢谢。 看到目录里面提到的打包平台 (http://hybrid.baidu.com/runtime/ ) 以为就这了,然后一股劲的找不到IOS打包方案。

    T5内核 是什么?包含什么? 或者哪里能找到关于这个的信息?

    跑了下 BlendDemo Xcode工程, 爆No architectures to compile for (ONLYACTIVEARCH=YES, active arch=x86_64, VALID_ARCHS=i386).错误, 按照网上的提示说要设置Build Active Architecture Only 为No,重新编译提示Unable to run app in Simulator An error was encountered while running (Domain = FBSOpenApplicationErrorDomain, Code = 4),重置模拟器,运行成功。

    #17
  • berg

    T5 内核是百度的浏览器内核,暂时没有太多公开信息,你可以简单理解成一个在性能上相比原生浏览器有所增强,并且能让你不用考虑浏览器兼容性的东东。

    #18
  • 叶小钗

    不错的样子,点赞

    #19
  • rockwxy

    其实就是 APPCAN中的 WINDOW 组件的概念,当时看中APPCAN的这个功能才放弃了PHONEGAP,页面跳转可以流畅多了,但是当页面WEBVIEW多了,内存泄露的情况怎么办?所以说还是有一定的挑战的

    #20
  • berg

    @rockwxy 没错,不过这个问题我们基本上解决了,现在正在做原生组件。

    #21
登录后回复,如无账号,请使用邀请码注册