混和合作开发
混和合作开发的隐晦解释是 Native 和 Web 控制技术都要用。但形式上,应用领域依然和应用程序毫无关系,使用者还是须要在 App Store 和 Android Market 浏览应用领域。而已在合作开发时,合作开发人员以 Native 标识符为市场主体,在最合适的地方性部份采用 Web 控制技术。比如在 iOS 中的 UIViewController 内置放两个 UIWebview(两个应用程序发动机,只拥有图形 HTML,CSS 和执行 JavaScript 的核心机能)。这样,部份介面就能在 UIWebView 中采用 Web 控制技术实现。
使得他们在终端合作开发中采用 Web 控制技术主要就动力在于,相比于 Native 控制技术,Web 控制技术具备众多竞争优势:
高工作效率的介面合作开发:HTML,CSS,JavaScript 的女团被证明在介面合作开发方面具备极高的工作效率。
虚拟化:统一的应用程序Mach国际标准,使得 Web 控制技术具备虚拟化优点。iOS 和 Android 能采用两套标识符。
热预览:可跨过发布平台独立自主预览应用领域。
那些竞争优势都和合作开发工作效率有关。Web 控制技术具备那些竞争优势的原因是,Web 控制技术是两个对外开放国际标准。如前所述对外开放的国际标准早已产业发展出来巨大自然生态,而且那个自然生态从 PC 时代产业发展至今已累积多年,合作开发人员能利用自然生态中工业生产的各式各样丰硕成果,从而省却许多多次重复工作。
在大型终端应用领域的合作开发中,工程项目标识符繁杂,通常还须要 iOS,Android,终端 Web 和 图形介面 Web 全网络平台全力支持。此种情况下,更高的合作开发工作效率就成了合作开发人员不得不考量的议程。这也是为什么虽然终端端 Web 控制技术在采用范围和操控性上有众多下风,依然有许多合作开发人员牺牲努力,积极探索如何在终端合作开发中采用 Web 控制技术。
他们也是如前所述以上各式各样考量,决定在新浪网的终端合作开发中课堂教学一些混和合作开发控制技术。
Rexxar 的背景
新浪网在 2014 年推出两个主应用领域:新浪网 App。那个主应用领域渐渐成长,逐渐全面覆盖了新浪网在 Web 上的大部份机能。随着工程项目的扩大,产品女团的扩充,新浪网App 成为了两个须要同时提供 iOS,Android 和终端 Web 网页的多网络平台全力支持的服务。工程控制技术项目组为了更淡然地应对此种状况,开始投入较大的心力提高项目组的合作开发工作效率。混和合作开发是其中主要就的措施之一。
由于工程项目早已产业发展到一定程度,他们并不期望砸毁过往的合作Attichy,也没有一切那样的话的雄心壮志和毅力。而已期望在不影响 App 的操控性大前提下,在最合适的地方性采用 Web 控制技术部份地提高合作开发工作效率。而新浪网App 中又确实存在部份网页是重度展示,并轻度交互的。那些网页恰恰适合采用 Web 控制技术来实现。
经过项目组的一些努力,工程项目中部份网页早已采用 Web 控制技术实现,并取得了不错的效果。工程师采用 Web 控制技术能以更快的速度完成产品需求,并且将一份标识符部署到两个网络平台。合作开发工作效率得到了实质性提高。即使不提热预览,减少 Android 工程项目方法数此种附带好处,他们也已喜欢上这项控制技术,决定在新浪网终端合作开发中推动混和合作开发控制技术的采用。
现在,他们将那个过程的主要就工业生产:Rexxar那个工程项目开源。一方面,是为了给大家提供一些借鉴的方向;另一方面,是为了提高工程项目本身的质量。他们知道还存在不少问题。所以,会悉心接受大家的意见和建议。
Rexxar 的介绍
Rexxar 是两个针对终端端混和合作开发架构。现在全力支持 Android 和 iOS 网络平台。并有两个 Web 基础库。
项目组中喜欢玩魔兽的同学将该工程项目命名为 Rexxar(《魔兽世界》中人物,出生于卡利姆多大陆的菲拉斯,同时具备雷骨兽人和南部菲拉斯野生食人魔两种血统)。
各网络平台标识符仓库地址如下:
Rexxar Web:https://github.com/douban/rexxar-web
Rexxar iOS:https://github.com/douban/rexxar-ios
Rexxar Android:https://github.com/douban/rexxar-android
Rexxar 主要就由以下三部份组成:
Rexxar Route,他们采用 URL 来标识每两个网页。在 App 中通过指明 URL 跳转到此网页。所以,需要两个路由表。通过路由表能根据 URL 找到两个 Rexxar Web 的对应资源来正确展示相应网页;
Rexxar Web,前端标识符库,由 HTML、CSS、JavaScript、Image 等组成,用来提供在终端客户端采用的使用者网页;
Rexxar Container,两个前端标识符的运行容器。它其实是两个内嵌的应用程序(WebView),他们为内嵌应用程序提供了一些必要的原生端全力支持,包括 API 的 OAuth 授权、图片缓存、Native UI 组件的调用等;现在有 Android 和 iOS 两个版本的实现。
在工程项目课堂教学中,Rexxar Web 和 Rexxar Route 由两个工程项目实现,并部署于同两个 Web 工程项目中。
Rexxar Route
Rexxar Route 比较简单,只须要表达两个路由表即可。他们采用了两个 json 文件来表达路由表。给出两个路由表的例子:
{ count: 4, items: [{ remote_file: “https://img1.doubanio.com/dae/rexxar/files/orders/orders-70dbdbcb1c.html”, uri: “douban://douban.com/orders[/]?.*” }, { remote_file: “https://img1.doubanio.com/dae/rexxar/files/related_doulists/related_doulists-1d7d99e1fb.html”, uri: “douban://douban.com/(tag|tv|movie|book|music)/(\w+)/related_doulists[/]?.*” } ], deploy_time: “Fri, 04 Mar 2016 11:12:29 GMT” }他们发布的每个版本的 App 安装包都会包含最新版本的 routes.json 文件。在 App 启动时,都会尝试浏览最新版本的 routes.json。在遇到无法解析的 URL 时,也会去浏览新版 routes.json。
Rexxar Web
Rexxar Web 是 Rexxar 前端实现。Rexxar Container 的实现和 Rexxar Web 的实现是分离的。Rexxar Container 对 Rexxar Web 采用何种控制技术实现并不关心。所以,你能选择自己的前端控制技术和 Rexxar Container 进行女团。比如,他们在业务层选择了 React 作为前端合作开发架构。
Rexxar Web 包括了三部份内容:
工具两套合作开发 Rexxar Web 所需的打包,调试,发布工具。
公共的前端组件通用的错误处理、Loading等效果
网页点击反馈效果
List 的全力支持
对 Rexxar Container 实现的 Widget 的调用ActionBar 的 title 定制
ActionBar 的 button 定制
Dialog
下拉刷新
Toast
有了那些组件,他们日常产品合作开发的难度就降低了。普通终端合作开发工程师经过一段时间的学习,也能像前端工程师一样,以 Rexxar 为工具为 App 做一些产品合作开发了。这部份能视为两个纯粹的前端工程项目。
Rexxar Container
他们采用混和合作开发控制技术提高合作开发工作效率的两个大前提是,不损伤 App 的采用体验。如前所述那个大前提,在 Native 和 Web 如何分工方面他们做了一些尝试。首先,为了保证采用体验,他们把 App 里网页切换留给了 Native。这样,每个网页(Controller 或者 Activity)都是两个 Container。Container 内嵌两个应用程序Mach。网页内的机能和逻辑在 Native 和 Web 之间如何分工呢?他们尝试过有几种策略:
纯应用程序方案:也就是 Native 除了扔给内嵌应用程序两个 URL 地址之外,就不做任何事情了,剩余的事情都由 Web 完成。这和用 Safari 或 Chrome 等普通应用程序打开两个网页并没有太多区别。而已他们固定了访问的地址。
前端模板图形容器方案:此种方案大部份事情由 Native 完成,Web 部份而已负责网页元素的呈现,不参与网页介面之于 Web 架构里模板图形库(例如,Jinja2)的作用。
Rexxar Container 方案:Rexxar 采用的方案介于上述两种方案之间。Rexxar Container 同样提供了两个运行前端标识符的容器。它也是两个内嵌的应用程序(WebView)。而已,他们并不是只扔给内嵌应用程序两个 URL 地址就放手不管了,还对对内嵌的应用程序做了许多合作开发,为其包装了许多附加机能。
Rexxar Container 方案中,Container 须要实现以下机能:
Rexxar Route 路由表的预览,早已在客户端保存;
为 Rexxar Web 前端标识符发出的 API 请求提供包装。带上必要的 OAuth 参数;
缓存 Rexxar Web 前端标识符所须要的静态文件,包括 HTML、CSS、JavaScript、Image(图片素材)等;
缓存 Rexxar Web 中所须要加载的资源文件,例如图片等;
通
此种实现方案,是如前所述保证采用体验的大前提下,尽量让 Web 控制技术多做一些事情的考量。
Rexxar Container 和 Rexxar Web 之间的交互混和合作开发课堂教学中,一般都会涉及到 Native 和 Web 如何通信的问题。这是因为他们把一件事情交给两种控制技术完成,那么它们之间便会存在有一些通信和协调。许多混和合作开发方案会采用 JSBridge(Android:JsBridge,iOS:WebViewJavascriptBridge) 来实现 Native 和 Web 的相互调用。
但在 Rexxar 中,我没有采用类似 JSBridge 这样的方案。而是通过从 Rexxar Web 发出 HTTP 请求的方式,由 Rexxar Container 截获的方式进行通信。Native 和 Web 之间协议是由 URL 定义的。Rexxar Web 访问某个特定的 URL, Rexxar Container 截获那些 URL 请求,调用 Native 标识符完成相应的机能。
例如,Rexxar 中 UI 相关的机能的协议如下:
请求 douban://rexxar.douban.com/widget/nav_title,能定义 Navigation Bar Title。
请求 douban://rexxar.douban.com/widget/nav_menu,能定义 Navigation Bar Button。
请求 douban://rexxar.douban.com/widget/toast,能出现两个消息通知 toast。
Rexxar Web 具体前端实现是在 DOM 中加入两个 iframe 来加载此 URL,以来完成对 Rexxar Container 的通知。
将 Native 和 Web 的通信以协议的形式规范起来,是因为他们期望 Native 和 Web 之间的通信是可定义的,可控的。有此种期望的原因是,他们以 Rexxar 完成的网页,不仅仅在 App 内采用,还会在终端 Web 网页上采用。他们的终端站点,特别是分享到外部(如微信,微博)的网页期望复用 Rexxar 在 App 内的工作丰硕成果。如果,任由合作开发人员自由地定义接口随意的依赖于原生实现的机能,那么他们就无法顺利地迁移到终端 Web 上去。国际标准应用程序并不全力支持 JSBridge 的大部份机能。但能看到他们早已实现的协议,大部份在终端 Web 是被能自动被忽略(比如,nav_title, nav_menu),或者他们也能较容易地以终端 Web 全力支持的形式再实现一次(比如,toast)。这样,Rexxar 中的前端业务标识符无需太多改动,即可迁移到终端 Web 和图形介面 Web 端。
Rexxar Container 的控制技术实现Rexxar Container 主要就的工作是截获 Rexxar Web 的数据请求和原生机能请求。Rexxar Container 截获请求之后,做相应的反应。此种 Native 和 Web 的交互被抽象成三种接口:
Decorator:修改数据请求。例如,数据请求加上 OAuth 认证信息。
Widget: 调用某些 Native UI 组件。例如,调起两个 Toast。
ContainerAPI:给 Web 两个 Native 的计算结果。例如,给出当前位置信息。
这三种接口都是由 Rexxar Web 发起某种形式的 URL 调用的。Rexxar Web 的业务标识符在 App 的 Rexxar Container 内工作方式,和在普通应用程序里差别不大。他们而已在 Web 控制技术的基础上做了一些拓展,保留了大部份 Web 原有的编写和运行方式。标识符都是国际标准 Web 式的,没有为原生终端合作开发做太多定制。因此,移植到 Web 网络平台,在各式各样应用程序中,标识符无需做太多修改就能正确运行。以 URL 作为协议,也为 Web 和 Native 划定了清晰的边界和数据传递方式。
他们为 iOS 和 Android 各合作开发了两个 Rexxar Container。iOS 和 Android 网络平台截获请求的方式由于网络平台差异,并不完全相同。但本质上都是在 Web 和 Native 之间实现了两个 Proxy。Web 发出的请求会被 Proxy 预先处理。要么是修改后再发出去,要么是由 Rexxar Container 自己处理。
具体的实现能参看两个网络平台的工程项目标识符。
Rexxar 网页执行过程
例如,客户端接到两个网页请求,要打开两个 URL:douban://douban.com/movie/1292052。Rexxar 的工作流如下:
根据 URL 查询本机缓存的路由表 routes.json,看是否能够找到对应的资源记录(一般是两个 HTML 文件)。如果找到不到,请求 Rexxar Route 服务,获得最新的全量路由表 routes.json,预览本地缓存,找到对应的资源记录;
根据路由表指示的 HTML 文件的路径,看本地是否找到对应的文件。如果找不到,请求 Rexxar Web 资源服务器,预览本地缓存;在 Rexxar Container 里展示该 HTML 文件;如有须要,会在 Container 中请求图片资源,图片资源也有缓存,Rexxar Container 会先检查本地缓存。如不存在,会请求 CDN 的图片或者图片服务器;
Rexxar Web 前端标识符在 Container 里继续执行,发出 API 请求。Rexxar Container 代理那些请求,为 API 请求添加 OAuth 验证,或增加某些参数;
Rexxar Web 前端标识符继续执行,根据 API 返回的结果,展示响应的网页,可能会请求 CDN 的图片或者图片服务器等;
Rexxar Web 前端标识符继续执行,如果须要修改 NavigationBar 等原生介面,可能通过定义好的协议请求 URL: douban://rexxar.douban.com;
Rexxar Container 拦截请求,按定义好的协议作出反应。例如,修改 NavigationBar 上的按钮。如果须要,会向 Rexxar Web 回调约定好的 Javascript 函数。
Rexxar 的问题
操控性混和合作开发的问题在于现阶段,Web 的操控性没法和 Native 相比。此种状况可能会长期存在。因为,前端标识符运行于内嵌应用程序之上,和直接调用原生系统相比,理论上总会存在操控性上的差距。他们现在基本是以规避的方式面对操控性问题:即操控性问题会明显影响到使用者体验时,他们就不采用 Rexxar 来做,而是采用传统 Native 老老实实写两份标识符,一份 iOS,一份 Android。当然,这就限缩了 Rexxar 的采用范围。
在 Rexxar iOS 中,他们做了采用 WKWebView 替代 UIWebView 的尝试。但是现在看起来这会是两个长远目标。WKWebView 在速度和内存消耗上都优于 UIWebView。但 WKWebView 并不完善。对于 Rexxar iOS 而言,最重要的缺陷是不全力支持采用 NSURLProtocol 截获 WKWebView 中发出的网络请求。所以在现有的 Rexxar 的实现中,并没有采用 WKWebView。但是,他们会持续努力,以寻找切换至 WKWebView 的可能性。
错误报告他们在应用领域中采用 Rexxar 之后,在收集到的 Crash Report 中,JavaScript 的相关错误,和应用程序相关的错误开始增加。而对这类错误,由于终端应用领域的采用环境更为复杂,错误报告经过了 JavaScript 发动机,原生系统两层之后,给出的错误信息并不够明确。他们在这方面的经验也并不多,导致他们还没有很好的办法降低这类错误。这对提高 App 的稳定性带来了问题。
总结
Rexxar 那个混和合作开发架构在新浪网终端合作开发中采用,确实在一定程度上提高了他们的合作开发工作效率。以前两个网页须要 iOS 和 Android 两位工程师各合作开发一遍,现在只须要一位工程师写一次前端标识符,甚至还能应用领域到终端 Web 上去。虽然 Rexxar 依然存在一些问题,和采用上的限制。但是在有限的采用中,他们依然收获不少。所以,在未来他们应该会持续推动 Rexxar 在新浪网终端合作开发中的采用。
期望那个 Rexxar 那个开源工程项目对大家能起到一点启示效果。并得到大家的反馈和建议,帮助他们提高。
全文完。感谢新浪网项目组的投稿。
赞助商:掘金是两个高质量的控制技术社区,让你不错过 i