Rexxar:豆瓣对混合开发的思考

  • 徐川

2016 年 12 月 6 日

话题:移动语言 & 开发架构

前段时间,豆瓣将自己的混合开发框架 Rexxar 开源了。豆瓣可以说是在国内对 HTML5 实践最早的一批公司,早在 2013 年的时候他们就应用了当时还显得超前的 Web Component 概念开发了 CardKit 移动 UI 框架。在移动开发上,豆瓣也采用了混合开发的模式,Rexxar 就是他们实践和思考的结晶。我采访了 Rexxar 的主要开发者之一郭麟,看看他们对混合开发的思考。

豆瓣使用混合开发的原因,是因为他们需要同时提供 iOS、Android、移动 Web 版本的页面,相对于同时开发三个版本,使用混合开发显然可以在代码重用、开发成本和效率方面有很大的优势,在权衡性能体验的前提下,使用混合开发是非常现实的选择。

Rexxar 是什么

Rexxar 是一个针对移动端的混合开发框架。支持 Android、iOS 和移动 Web。

Rexxar 主要由三部分组成:

  • Rexxar-web:前端代码库。包括一套打包、调试、发布工具,以及公共前端组件,和对 Rexxar Container 实现的 Widget 的调用。
  • Rexxar-Router:路由表,将每个页面分配一个服务器端链接,以及一个本地 URI,通过路由表来访问页面。
  • Rexxar-container:增强版 WebView,封装了一些 Native API 支持,包括 OAuth 授权、图片缓存等。

Rexxar 目前已经开源,并且分为 3 个项目,你可以只使用其中某个项目来开发对应平台的代码:

https://github.com/douban/rexxar-web

https://github.com/douban/rexxar-androidhttps://github.com/douban/rexxar-ios

混合开发的注意点

对于混合开发,很多团队都有过实践,从大家分享的内容来看,重点无非以下几类:

  • 增强 WebView:原生 WebView 基本是 PC 平台浏览器内核的移植,但对于移动场景并不完全适合,各种硬件 API 得不到 HTML5 原生支持。因此对于 WebView 的种种 Hack、增强应运而生,甚至出现了基于增强 WebView 提供第三方服务的。
  • 路由:应用内跳转由于加入了 WebView 而变得复杂起来,同时由于组件化、模块化带来的问题,路由也成为人们讨论的重点。
  • 缓存:移动网络条件差,为了用户体验,必须要做资源缓存和预加载。
  • 通信:即 HTML5 和 Native 之间的通信。利用系统提供的桥接 API 可以实现,不过在应用上还有着一些坑点和安全问题。

这些问题大部分已经有了最佳实践,Rexxar 就是其中一个解决方案。在混合开发中一般有两种方案:纯浏览器方案、前端模板渲染容器方案,Rexxar 则处于两者之间。

Rexxar 的设计者对于 Rexxar 使用场景有明确的定义:页面是重度展示,并轻度交互的。所以,除了比较简单的应用之外,如果对使用体验有追求,大概很难仅仅用 Rexxar,或者其他某种混合开发完成。

对于扩展功能,Rexxar 留出了清晰易用的接口。项目中也提供了几个扩展 Rexxar 功能的实例,文档也较为完整。郭麟他们在豆瓣 App 中其实也使用相同的接口做了一些扩展,只是由于这些扩展和豆瓣 App 的业务绑定较深,就没有放入 Rexxar 项目。

Rexxar 在客户端的实现其实就是一个定制了更多功能的 WebView。而且,Rexxar 使用的是系统的 WebView。所以,它对 App 的体积没有影响。但是,同时使用很多个 WebView 带来的内存问题,Rexxar 同样也有,这是需要注意的。

Rexxar 的 Crash 有两种:

  • 一种是 JavaScript 的错误,也就是应用逻辑的问题。这类错误他们在 WebView 中做了捕获,然后通过 App 的日志系统发回服务器。
  • 一种是 WebView 的 Crash,这种错误 WebView 自己无法捕获,现在是通过 fabric,Umeng 这种原生的 Crash 收集系统收集。

从上线了 Rexxar 之后,JavaScript,WebView 相关错误日志和 Crash 报告是有增长的。所占的比例和 Rexxar 的页面数量相关,一直在变化,但都未超过 10%。但由于豆瓣 App 中主要还是原生页面占大多数。所以,Rexxar 带来的 Crash 所占的比例并不大。

他们也正在研究,在移动环境下如何定位 Rexxar 页面的错误,如何调试,如何修正这些错误,并将其加入基础设施里面。

为什么不用 PhonGap/Cordova

在混合开发中早已有了很成熟的方案,就是 PhoneGap 和它的后继者 Cordoba. 为什么豆瓣还要造自己的轮子呢?

郭麟说,如果 Hybrid 方案定义为前端和原生技术的混合使用,那他们认为 PhoneGap/Cordova 严格来说不算是 Hybrid 方案,因为它的目标是全面使用前端技术开发移动应用,而不是前端和原生技术混合使用。但是,包括 Cordova,还可以加上 React Native,以及 Rexxar 的目标是一致的:使用前端技术来开发移动应用,提高工程效率。

豆瓣实际上使用 PhoneGap 开发过一款移动 App,并在 AppStore 上架了,这个应用叫豆瓣音乐人,因此,其实豆瓣对 PhoneGap/Cordova 已经有一定了解和使用经验。为何在开发豆瓣 App 时又造了一个叫 Rexxar 的“轮子”呢?这是因为,他们对 PhoneGap/Cordova 这个项目的理念并不完全赞同,Rexxar 的出发点和 PhoneGap/Cordova 并不一样。

PhoneGap/Cordova 这个项目极具野心。它希望完全使用前端技术完成移动开发。所以,可以看到它尽力让前端技术完成尽量多的开发工作,只在前端无法直接调用的原生系统功能方面提供了前端可用的接口。主流的 PhoneGap/Cordova 项目将业务逻辑都实现在一个 WebView 中。目标是,让开发者只使用前端技术就可以完成一个移动应用的所有开发工作。这种做法需要有一个前提:前端技术可以解决移动开发的所有需求。他们认为 PhoneGap/Cordova 这个理念在现阶段有些过于理想化了,或者说过于激进了。

Rexxar 则相对实际,或者说保守一些。郭麟表示,他们仍然认为,现阶段,甚至在相当遥远的未来,移动开发中前端技术都不太可能完全代替原生技术。但他们同时承认,移动开发中总是存在部分功能是适合使用前端技术完成的。在他们的认识中,前端技术和原生技术应该是共存的。移动开发中,前端技术不会完全代替原生技术;而有了前端技术的加入,移动开发的效率会提高。基于这种认识,豆瓣开发了 Rexxar。

可以看到,Rexxar 立足于在一个原生项目使用前端技术,而不是整个项目都使用前端技术实现。他们甚至提供一个页面部分使用 Rexxar 完成,部分使用原生技术实现的方案。豆瓣希望借助前端技术优秀的排版能力、开发速度、通用性,来弥补原生开发在这方面的不足。在微信作为主要内容分享渠道的今天,这样做还带来了一个额外的好处,Rexxar 页面可以平滑的使用在微信中。

总结而言,如果 Rexxar 和 PhoneGap/Cordova 比较的话,大目标是一致的:使用前端技术开发移动应用。实现技术栈差不多:使用 WebView,提供调用原生功能的接口。但是,出发点不一样。PhoneGap/Cordova 致力于完全使用前端技术进行移动开发;Rexxar 致力于在移动项目中部分使用前端技术。

移动开发者要学习前端技术

目前,豆瓣移动团队大约有十多位客户端工程师,其中 iOS 和 Android 各一半。另有一位优秀的前端工程师专门支持豆瓣 App 中的混合开发,他负责 Rexxar Web 的开发,提供基础设施。同时如果有一些较复杂的业务要用 Rexxar 实现,他也会参与和指导业务开发。

使用 Rexxar 这类混合开发技术,使得团队开发的技术栈向前端技术偏斜了。所以,较理想的配置是团队中加入较优秀的前端工程师,由他来处理基础设施的开发,和疑难问题的解决。同时,整个团队需要理解混合开发所带来的优势,认可这个开发方式的转变,并且愿意学习和调整自己的技术栈。

在项目中,在合适的场景中,豆瓣会优先使用 Rexxar。在团队中,他们鼓励非前端工程师学习和使用前端技术。为此,他们专门组织了关于前端技术内部培训,让有意愿的非前端工程师具有了可以使用前端技术进行日常开发的基本能力。在豆瓣 App 的日常开发中,大部分 Rexxar 页面都由客户端工程师完成,前端工程师会帮忙做 Code Review 和解决疑难问题。

Rexxar 与 React Native

豆瓣在实际使用 Rexxar 的时候,使用 React 作为前端框架。对此郭麟解释道,Rexxar 本身对前端框架的选择没有要求,只是他们选择了 React 来实现业务层,而当时 React Native 并未发布,经过对 RN 的了解后,他们并未否定使用 RN 的可能性。

在他们看来,React Native 同样是一种使用前端技术开发移动应用的技术方案,这和他们开发 Rexxar 的目的是一致的。只是,Rexxar 仍然在停留在浏览器引擎中,而 Facebook 激进地脱离了沉重的浏览器引擎,架设了他们自己的 Web 通向 Native 的桥梁,这是一个很大胆的方案。

在 React Native 发布后,他们马上就组织研究,并做了小范围的实践,也与同行做了交流。结论是,现阶段,React Native 还稍显稚嫩。对于一些技术栈比较特别的团队,比如 Web 经验特别丰富,前端工程师特别优秀,但又缺乏客户端工程师的情况,React Native 是一个快速切入移动应用市场的技术选择。但就豆瓣 App 的情况和 React Native 的现状而言,使用前端技术进行移动应用开发方面,他们还坚持留在 WebView 中,不会使用 React Native。

当然,React Native 一直在发展和进步。如果,有一天 React Native 和 React 可以在代码级别移植,他们也许会尝试从 WebView 迁移到 React Native。毕竟 WebView 的性能仍然弱于原生。

总结与展望

豆瓣 App 和研发团队都经历了从小到大的发展过程。Rexxar 是这个发展过程中,解决工程效率的一个方案。在豆瓣移动开发中使用 Rexxar,确实在一定程度上提高了他们的开发效率。以前一个页面需要 iOS 和 Android 两位工程师各开发一遍,现在只需要一位工程师写一次前端代码,甚至还可以应用到移动 Web 站上去。前端技术开发界面方面开发方面也有效率上的优势。热部署能力,使他们规避了发布移动应用的审核过程,也让 bug 修复过程更便利。

豆瓣将 Rexxar 这个项目开源,一方面,是因为提高移动开发的工程效率是一个普遍问题,而他们的实践结果也证明 Rexxar 确实帮助改善了工程效率。所以,他们认为 Rexxar 应该能给大家提供一些借鉴的方向。另一方面,是为了提高项目本身的质量,没有方案是完美的,Rexxar 也还存在不少问题。开源这个项目,促使他们提高了整个项目的代码质量。同时,也更容易听到大家的意见和建议。

虽然 Rexxar 仍然存在一些问题和使用上的限制。但是在有限的使用中,豆瓣 App 团队仍然收获不少。在未来他们会持续推动 Rexxar 在豆瓣移动开发中的使用。郭麟表示,对于 Rexxar 未来的发展,他们主要关注两个方面:

  • 一方面是基础设施,比如,如何在产品中,更好地监控 Rexxar 页面出现的问题,如何调试和解决 Rexxar 页面出现的 bug。如果希望在大型项目中使用 Rexxar,这些基础设施是应该配备的;
  • 另一方面是性能,Rexxar 仍然跑在浏览器引擎中。浏览器引擎这个中间层提高了工程效率,但也因为性能问题局限了其使用范围。所以,他们会花一些精力提高 Rexxar 的运行效率。比如,Rexxar 的 iOS 版一直在关注从 UIWebView 迁移到 WKWebView 的可能性。

参考文章:

豆瓣混合开发实践

豆瓣的混合开发框架 Rexxar豆瓣 App 的模块化实践《CardKit & DOMO UI - 移动时代技术与设计的十字路口》技术篇豆瓣音乐人 app 的 PhoneGap 实践

移动语言 & 开发架构