天天看点

语雀 App 跨端技术架构实践

作者:闪念基因
语雀 App 跨端技术架构实践

本文基于蚂蚁集团技术专家张亚峰(牧秦)在「RTC Dev Meetup • 杭州站丨大前端时代的业务架构和跨端实践」活动中分享内容二次整理。

关注公众号「声网开发者」,回复关键词「702」即可下载活动相关 PPT 资料。

语雀 App 跨端技术架构实践

声网开发者与开发者分享实时互动领域的开发实践、算法研究与前沿技术。121篇原创内容

公众号

目录

1. 语雀整体介绍

1.1 语雀整体介绍

1.2 语雀整体技术选型

2. 语雀 App 架构推演 & 设计

2.1 阿里云 mPaaS

2.2 移动端架构思路

2.3 移动端方案对比

2.4 语雀的选择

2.5 语雀 App 架构图

2.6 三层架构

2.7 通用 JSBridge 设计

2.8 ReactNative ↔ H5 双向消息流动

3. 跨端同构实践

3.1 基于 ViewModel 同构列表页

3.2 Request 请求同构

3.3 消息三端同构

4. 即时渲染桌面软件开发框架

4.1 性能调优

4.2 稳定性监控

4.3 研发 & 交付效率

4.4 交付质量

5. 问题 & 挑战

5.1 ReactNative Crash 问题

5.2 Native 组件编写

01

语雀整体介绍

1、语雀整体介绍

首先介绍一下语雀的整体情况,语雀是蚂蚁集团推出的一款笔记与文档知识库的管理 & 协同工具,目前整个集团内部的的员工大约有 10 万多人日常也在使用这个工具,并且现在已经开始对外提供服务了。图 1 所示为语雀基于 Electron 推出的 Mac 和 Windows 桌面端,包括文档列表以及相关的管理。还有应对移动端使用的工作场景以及小程序。

■图 1

另外,从去年开始我们着手开发了移动端 App,并于今年 2 月份顺利发布上线。图1 右侧展示的是 Android/iOS 的 App 截图。

2、语雀整体技术选型

接下来我将介绍一下语雀的整体技术选型。语雀在内部运营中的名称为 Skylark,它的整个项目位于一个大型的 Codebase 中。其中的服务端、桌面端,移动端等的所有代码包含在这个 Codebase 中,如图 2 所示。

■图 2

其中服务端采用 Node.js、Egg.js,还有一些服务是基于 Java 开发的,但是这部分目前相对比较少。PC 端主要采用 React 技术栈,桌面端采用 React 和 Electron,小程序采用 React 以及 H5 离线包。大家可以发现,整个技术是基于 JavaScript 或者 TypeScript 来做的。

整个语雀技术团队没有区分前端或者后端,大家都是全栈式开发。一个团队成员可能既要完成一个需求的服务端部分,同时也要做前端的代码研发。在此基础上我们还进行了移动端 App 的设计和开发,这部分内容我们接下来将详细介绍。

02

语雀 App 架构推演 & 设计

1、阿里云 mPaaS

语雀 App 的架构是如何设计的呢?首先整个集团已经有一套比较稳定的移动端框架 —— mPaaS,该框架是基础的移动端开发框架,如图 3 所示。

■图 3

它现在在阿里云上也对外提供服务,也有很多三方公司都基于这个框架来开发自己的 App,它提供了配置开关服务、Push 服务、基于长连接的 Sync 服务、H5 容器&离线包、移动分析和移动网关等基础服务。

2、移动端架构思路

语雀 App 跨端技术架构实践

■图 4

在这样的技术品牌打底的基础上,我们进行了移动端的架构设计,如图 4 所示。首先选用 mPaaS 作为底层的框架基础。然后客户端的 Native 框架层尽可能轻量、与业务解耦。

接下来针对渲染层,我们考虑动态或者 Hybrid 方案,比如要根据文档阅读页或编辑器的业务特性来选用具体的框架。最后还要考虑同构开发,因为现在已经有很多的多端业务模块在运行中了,如果能够实现同构开发,那么这些代码或者经验都可以被复用。

3、移动端方案对比

图 5 所示为移动端的框架对比,相信大家已经在很多场合都看过了,其中基于 H5 Hybrid 的方案( H5 或者离线包),其性能稍微差一些。纯 Native 的性能虽然很高,但是开发成本也相应增加,上手也比较困难。现在一些公司也有自己内部的 Hybrid 开发方案。

语雀 App 跨端技术架构实践

■图 5

4、语雀的选择

那么语雀是怎么选择呢?首先我们希望语雀的体验是比较流畅的,能够贴近 Native App 的各种体验;其次希望能做到一次编写,双端运行,兼顾开发效率;然后就是能够兼具 Web 的研发体验,使得团队的 Web 技术栈的同学能够快速参与进来;最后是期望能够同构复用,这样之前沉淀的经验、模块可以直接复用。

5、语雀 App 架构图

■图 6

接下来我为大家介绍一下语雀 App 的整体架构,如图 6 所示。最底层是 mPaaS 的基础设施,前面已经提过了,其中包含了一些通用基础组件。中间层是 Native 基础能力层,这一层提供了基础的账号管理、升级管理、各种 Bridge 以及其他服务。

接下来我们可以看到两个向上的箭头,RCTBridge 负责把基础服务暴露给 ReactNative;JSBridge 则是将这些服务同步暴露给 H5。然后 ReactNative 和 H5 之间通过 RCTEvent 进行通信。

ReactNative 层主要实现页面生命周期、业务跳转、页面呈现等;H5 主要用来承载对更新速度等要求比较高的业务。再上层是 CI/CD 以及 DevTools、环境切换、单元测试等,充分支撑语雀的上层具体业务。

6、三层架构

■图 7

可以看出整体是一个三层架构,如图 7 所示。在 Native 层我们采用 Kotlin 和 Swift 来实现。然后 ReactNative 层采用 TypeScript/同构 Web 方式来实现,这一层主要用来实现列表或者对流畅性、体验要求比较高的页面。而 H5 层主要结合语雀的具体业务特性来使用:比如要用 ReactNative 来实现一个富文本编辑器或者阅读器,那么它的代价是非常高的,这种情况就使用 H5 来实现,对页面加载速度要求比较高的 H5 页面,我们使用离线包来做页面资源加速。

7、通用 JSBridge 设计

接下来讲一下通用的 JS bridge 设计,如图 8 所示:

■图 8

RN 和 H5 共用一份 JS Bridge 实现,将底层的一些通用服务能力,分别通过两个 Bridge 暴露上去,可以让 H5 和 ReactNative 直接调用。图 8 右侧展示了 H5 和 ReactNative 调用 Bridge 的代码,其实除了第一行不一样之外,后面的 Bridge 调用和结果处理都是一致的的。

8、ReactNative ↔ H5 双向消息流动

■图 9

接下来看一下ReactNative ↔ H5 双向消息流动。比如在进入语雀富文本编辑页面后,底部是一个 ReactNative View,上面嵌入了 WebView/WKWebView 用于展示编辑页。这就涉及到了 H5 和 ReactNative 的双向消息流动。

如图 9 所示,蓝色的箭头是 H5 调用 ReactNative,红色箭头是 ReactNative 调用 H5,其实是通过 postMessage 发送消息,H5 侧通过 onMessage 接收消息。H5 调用 ReactNative 也是通过 postMessagee 发送消息,然后 ReactNative 侧通过 onMessage 监听。

03

跨端同构实践

1、基于 ViewModel 同构列表页

接下来看一下跨端同构实践,那么什么是同构呢?如图 10 所示,我们看到一个Web 页面,其中包含了一些列表,每个列表项包含操作选项入口,用户点击操作菜单后,可以对列表进行排序、筛选或者删除等操作。小程序和移动端 App 也是这样。

语雀 App 跨端技术架构实践

■图 10

这三个页面的共性就是它们都是一个列表页,同时需要请求网络加载数据,另外可能还包括分页操作等。当然这里没有特别复杂的交互,点击操作菜单可以进行删除等操作。我们知道了这些共性,就可以方便的进行同构开发。

具体列表页怎么基于 ViewModel 进行同构开发呢?如图 11 所示,我们抽出通用的 ViewModel,在其中做 loading 管理、数据管理等,网络请求管理可以通过 recentListAll 请求,列表页数据通过 state 暴露出去,同时还有 handler 操作可以执行拉数据、删除条目等操作。这样最后返回的是状态集和一个操作列表。

语雀 App 跨端技术架构实践

■图 11

在上层使用的时候,比如说我们使用这样的 ViewModel 渲染的最终页面时候,在各个平台上只需重写渲染部分,返回对应平台的 View/div 即可。通用的重逻辑、重请求的代码都是同构开发的。

2、Request 请求同构

■图 12

如图 12 所示,在语雀项目中有一个 isomorphic 同构文件夹。下面有三个子模块,分别定义了三个平台上对应的 request.js 实现。具体实现中,Web 侧使用浏览器的 fetch 接口,小程序侧可能调用 AlipayJSBridge,ReactNative 侧则调用 LarkRCTBridge。

数据请求接口的具体定义(如下图的 web.mime.js/recentListAll 接口),使用的是从 request.js 暴露的 get/post/put/delete 等方法,最终构建打包的时候,通过 alias 将 request.js 在各个平台进行重写。

3、消息三端同构

■图 13

接下来介绍一下语雀 App 中消息的三端同构,如图 13 所示。比如我们在 Web 侧有这样一个消息列表,只要别人关注了我或者评论了我的文档,就会产生一个消息。小程序和 App 侧的 UI 也是类似的。还有一个场景就是 App 消息推送,别人对我的文档进行操作时,要在移动端设备系统通知栏展示出来:

那么在这种情况下我们该怎么做同构开发呢?语雀现在有 70 多种消息,如果要为三端都写一份实现的话,可能要写 230 多次。这显然是不现实的。此时就可以基于同构的方案来做。同构部分包括各种消息的同构 Builder 生成器,分别通过模板 Notification Context 构建三端渲染结果:服务端得到消息字符串用于展示,在 H5 或者 Web 端渲染出原生的 div、span 等元素,在 ReactNative 侧渲染出 View、Text 等 View。

■图 14

举一个例子,比如在图 15 所示的 Context 上有一个 buildActor、buildSubject 和 buildLink 来渲染用户头像或者链接等。接下来服务端、小程序和 ReactNative 提供三个 Context 实现就可以了:

■图 15

04

性能 & 稳定性 & 交互

接下来介绍在采用前面介绍的方案之后,性能、稳定性和交互方面的相关实践。

1、性能调优

我们在实际开发中,遇到了一些性能问题。首先是 App 启动速度优化,App 启动时一般需要展示闪屏页、隐私协议授权页、权限授予等,我们将闪屏页和主 Activity 合二为一,同时采用 Pipeline 方案定制启动细节,最终启动速度得到了较好的优化。

第二个就是小记编辑器启动速度优化。前面说到编辑器是利用 H5 来做的,但是如果用户有了灵感,想要做一些记录,如果编辑器启动慢,那么用户是很恼火的。为此,我们对小记做了一个单独的编辑器,通过离线包将其预置到客户端,或者通过动态下发的方式更新,能够第一时间快速拉起。另外,我们还预先判断了哪些情况下用户可能要唤起小记,这种情况预先创建 WebView、预加载资源,编辑器的体验得到了保障。

另外,我们还进行了 WebView 的加载优化,对一些通用 JS 和 CSS 做了一些资源包的预加速。

2、稳定性监控

通过 mPaaS 埋点 SDK 统计埋点信息,我们通过 mPaaS 监控后台能够看到一些基础数据,同时会把这些埋点数据流到内部监控大盘、钉钉群日常播报,也可以通过语雀实时上报通道进行 ErroeBoundary/JSException 实时播报,具体如图 17 所示。

■图 17

3、研发 & 交付效率

语雀 App 在三层架构在实践下,较好的保证了的研发效率和交付效率。我们每周会发布一个内测版本,小功能能够快速滚动内测发布,内测用户也能够积极反馈。同时,我们每两周会发布一个小版本,每个月可以发布一个大版本。

现在整个架构的 Native 侧是重服务轻 UI:Android 和 iOS Native 实现的模块,基本上全是服务型的代码,通过JSBridge 暴露给上层。ReactNative 侧则是重 UI 轻服务:它只是做一个单纯的渲染层,Native 服务层接口 & 能力稳定之后,很少变动,上层就可以用 ReactNative 随着业务快速滚动开发交付。

4、交付质量

交付质量这块,作为 CI/CD 的一部分,我们的 QA 同学提供了非常充分的自动化测试,每天会进行自动化测试巡检,用最新的包进行滚动测试验证,同时出具报告,有问题的情况会第一时间通知开发同学修复。如图 18 是自动化测试报告的截图:

语雀 App 跨端技术架构实践

■图 18

05

问题 & 挑战

最后介绍一下我们在用 ReactNative 方案的时候遇到的一些问题和挑战。

1、ReactNative Crash 问题

语雀 App 跨端技术架构实践

■图 19

ReactNative Crash 可能是一个老生常谈的问题。比如说我们遇到图 19 所示的 Crash 信息,看 Native 堆栈完全不知道问题出在 ReactNative 代码的哪个模块中,这样排查难度是相当高的。这种情况我们只能尽可能尝试复现场景、联系用户等方式修复:

2、Native 组件编写

日常开发中,可能需要一些 Native 组件,常见的情况是,社区没有或者社区组件能力不匹配业务需求。比如语雀 App 底层的基础服务、UI 组件都是由 Native 提供的,语雀现在提供了 86 个 Native JSBridge。还有一些 UI 组件需要 Native 提供双端的实现,比如NebulaWebView、ImagePreviewer、PullToRefreshView 等,具体如图 20 所示:

语雀 App 跨端技术架构实践

■图 20

最后做一个简单的小结,我们提出三层架构的最主要思路有三个具体的思考点:一是结合业务的特点去设计整体架构;另外就是可以尽量复用手头或者已有的组件或者社区组件;第三个是结合语雀现有的代码情况和团队整体研发匹配情况。

在整个过程中,我们提出的同构设计思路和开发模式,在开发实践中得以充分使用,可以说到了较好的验证。

作者:张亚峰

来源:微信公众号:声网开发者

出处:https://mp.weixin.qq.com/s/8xGS2n59S1WQ1d2yfB3OyQ

继续阅读