【AICon】探索八个行业创新案例,教你在教育、金融、医疗、法律等领域实践大模型技术! >>> 了解详情
写点什么

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

  • 2014-07-15
  • 本文字数:4744 字

    阅读完需:约 16 分钟

故事背景

百度轻应用已经推出半年多了,在市场上已有一定的影响力。但同时我们发现,开发者之所以使用轻应用,看中的是百度的渠道分发能力,而在体验上和 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 )关注我们,并与我们的编辑和其他读者朋友交流。

2014-07-15 12:455041

评论

发布
暂无评论
发现更多内容

华中科技大学网络空间安全学院正式加入openGauss社区

openGauss

加速文件传输协议如何工作

镭速

MobTech ShareSDK|如何从分享到回流

MobTech袤博科技

达观助手AI写作下载安装教程及特色功能详解,速速收藏体验!

NLP资深玩家

不会吧?该不会还有企业没实现员工赋能吧!绝对是你没选低代码的问题!

加入高科技仿生人

知识管理 低代码 系统开发 员工赋能

openGauss社区三月运作报告

openGauss

前端开发培训机构怎么样

小谷哥

DevOps系列之 —— 持续规划与设计(三)敏捷项目管理的方法【Kanban 与 Scrum】

若尘

DevOps #DevOps 三周年连更

云原生时代全链路观测体系构建

嘉为蓝鲸

车企外卷:一个关于智能手机的“围城故事”

脑极体

手机 车企

一文读懂域名注册

火山引擎边缘云

证书 域名 域名服务器

云和恩墨大讲堂 x 长江鲲鹏 x openGauss Meetup(武汉站)圆满落幕!

openGauss

Node.js实现JWT应用到服务器

格斗家不爱在外太空沉思

node.js 三周年连更

vue3 +ts 如何安装封装axios

肥晨

Vue3 三周年连更

除了价格降70%,关于对象存储预留空间你还需要了解这些

云布道师

云存储

别再吐槽公厕了!杭州智慧公厕解决方案带来惊喜

光明源智慧厕所

智慧城市

江苏智慧公厕:让厕所成为城市新名片

光明源智慧厕所

智慧园区

盘点 8 款好用的 API 接口文档管理工具

Liam

程序员 接口文档 API 接口规范 接口编写

HuggingGPT 强势来袭,LLM+ 专家模型,迈向更通用的AI

Zilliz

Zilliz Towhee ChatGPT LLM huggingface

zookeeper的节点加密方式及分布式锁实现过程

浅羽技术

三周年连更

便捷高效,Notion AI比ChatGPT更加香!

南城FE

人工智能 AI 前端 ChatGPT

软件测试/测试开发丨基于 JMeter 完成 Dubbo 接口的测试

测试人

dubbo 软件测试 Jmeter 自动化测试 测试开发

一文读懂Annotation

老周聊架构

三周年连更

ChatGPT大面积封号+停止注册?最火概念要凉?

这我可不懂

低代码 源代码 ChatGPT

5 分钟带你小程序入门 [实战总结分享]

程序员海军

小程序 微信小程序 前端 三周年连更

全球首个完全开源的指令跟随大模型;T5到GPT-4最全盘点

OneFlow

openGauss都做了哪些算子优化工作?

openGauss

大数据学习培训机构该怎么去选择

小谷哥

慌了?ChatGPT吃我的饭,还要掀我碗

引迈信息

AI 低代码 ChatGPT JNPF

devops|中小公司不要做研发效能度量

laofo

DevOps 研发效能 效能度量 DevOps工具链 研发效能度量

openGauss 5.0.0版本正式发布!

openGauss

BlendUI,让webapp的体验和交互得到质的提升_语言 & 开发_雷志兴_InfoQ精选文章