iBox-面向Flutter的一站式研发工作台

4621次阅读  |  发布于2年以前

一 前言

Flutter 一码多端的特性,解放了端上同学的人力,带来了研发效率的提升,淘特技术团队因为早期双端研发同学数量不匹配以及对研发效率的诉求,也是阿里集团内部比较早在业务上落地 Flutter 的团队之一。

虽然有了一码多端的便利,但是伴随而来的还有研发链路中的各种问题,例如研发环境搭建,双端工程环境,集成发布流程繁琐等等。为了深入了解开发同学们的痛点,我们在团队内部发起了一份问卷调查。

我们针对研发幸福感指数以及研发链路中遇到的各种问题进行了调查。结果如下:

在研发幸福感指数的打分中平均得分是 3.38(5分制)。我们针对影响研发幸福感的问题进行了分析,筛选出了一些大家普遍认为影响研发效率的问题。其中排名最高的是研发环境+工程环境(Flutter相关)的搭建,开发调试(Flutter相关)等问题。

接下来我们就来看看这些问题的具体痛点,以及解决这些问题的时候面临的一些挑战。

二 问题与挑战

1 问题

在影响研发幸福感的问题中,主要是以下三个方面的问题比较突出。

1)研发环境问题

研发环境配置是编码的前置工作,它也会影响新人落地对团队研发体验的第一印象。由于 Flutter 涉及 Android 与 iOS 双端的环境配置,导致不熟悉另一个端的同学配置起来,十分麻烦,上手难度高。另外,Flutter 本地版本不一致,缺乏 Flutter 版本管理工具,文档零散更新不及时,这些都极大的耗费了团队同学的精力。

2)工程环境问题

解决了研发环境问题,还需要解决工程环境问题,双端工程架构复杂,不熟悉某个端的同学面对编译问题难以解决。甚至很多同学就直接放弃了配置另外一个端的工程,平时开发只对着自己熟悉的端调试,违背了 Flutter 双端开发的理念。

点评:从团队的调研采访来看,一个新人同学搭建 Flutter 的研发环境和工程环境,先需要一天时间搭建好基础环境,后面的两三天时间折腾各种编译问题,特别是 iOS 的相关环境对于 Android 同学来说想要完整跑起来十分费力。

3)集成流程问题

等到代码开发测试完成以后,集成步骤多,平台间来回切换,集成流程割裂,没有形成完整的 SOP。整个集成流程既费时费力,又容易引发质量问题。

点评:现有的 Flutter 模块集成流程分为六步:1 模块分支代码合并 -> 2 模块生成新Tag版本 -> 3 主工程修改模块版本号 -> 4 主工程代码合并 -> 5 主工程生成版本号 -> 6 摩天轮提交正式包打包,步骤繁琐,需要在 Aone、MTL 等平台来回切换,而且手工操作各种版本号,很容易引发线上质量问题。

2 挑战

为了解决这些问题,之前也有沉淀一些文档和脚本,但是文档有很多步骤、命令,弄错任何一个就可能导致环境搭建出错,另外文档有时候也没有及时更新。

我们想如果能有一个桌面端 GUI 形式的研发工作台,研发同学日常研发遇到的各种问题都可以在这上面解决,新来的同学也可以借助这个研发工作台快速落地,那对研发的幸福感将是一个质的提升。

于是我们便决定打造一款桌面端的研发工作台,在实现这个目标的过程中我们也遇到了很多挑战。

1)如何降低开发同学的接入和使用成本

  1. 接入和使用成本。研发工作台本来作为一款工具软件,它本身如果再操作复杂,需要看各种文档,那就背离了工具软件简单易用的初衷,所以复杂操作一键化是做相关功能时必须做到的,例如软件环境一键配置,工程环境一键配置,一键集成发布等,很多功能都是按照这个思路来做的。
  2. 兼容现有的研发环境和工程环境。除了新来的同学,大部分开发同学的电脑上已经有了部分环境,如何与现有的环境共存,不改变开发同学现有的使用习惯,也是我们重点考虑的问题。

2)如何保障架构设计的合理性

我们想把研发工作台打造成一个人人都可以参与进来共建的开放平台,因为个人的时间是有限的,工作台本身作为一个工具集的聚合,需要更多的同学参与进来,更多的 idea 落地,所以如何做好仓库权限控制以及设计一个好的插件化框架就显得很重要。

3)新技术的落地,相关问题需要自己探索解决。

在桌面端研发工作台的开发中,我们使用的是 Flutter Desktop 技术(至于原因,技术调研部分会讲),国内目前 Flutter Desktop 技术在生产环境落地的并不多,相关经验还比较缺乏,遇到一些问题的时候,需要自己去探索解决。

接下来我们就来看一看我们为了解决这些问题,在 iBox 上设计了哪些核心的功能,以及这些功能是如何解决这些问题的。

三 技术全景

1 技术调研

业界的客户端研发工作台的发展现状。如下所示:- 业界:EasyBox,MBox 等工具。这些工具的核心一方面在于解决 Native 环境搭建,开发效率低的问题。另一方面深度封装 Git、Cocoapods,统一开发模式。

整体上看是一个客户端研发工作台落地的契机,业界有团队在尝试,淘特在 Flutter 研发链路也有痛点和需求。既然要进行桌面端开发,选择一个桌面端开发框架就成了首先要考虑的事情,当下比较流行的桌面端开发框架主要有以下两种:

通常我们在做技术选型的时候会从问题解决,团队现状,技术领域,业务趋势等几个方面层层递进去思考。

基于以上思考,我们最终选择了 Flutter Desktop。有了开发框架,我们接着来看看 iBox 的架构设计。

2 功能设计

iBox 的核心定位

iBox 是一款基于 Flutter Desktop 技术栈研发的一站式、多样化、可定制的研发工作台。提供从研发环境到集成发布全流程的研发支持。核心功能包含工作台、研发环境、工程管理、引擎管理、社区生态、变更单管理与工具箱等。

iBox 在功能设计上分为工作台、研发、发布、工具箱四大板块。其中研发、发布、工具箱又各自包含了很多子模块功能。

我们着重介绍一下工作台、研发环境与工程管理、社区生态、变更单管理等核心功能,让大家对 iBox 的整体功能有一个基本认识。

工作台

提供了最近变更单,常用平台快捷入口等功能,让常用功能一键直达。另外工作台还预留了技术展示 Banner 位的功能,可以展示一些团队内外的优秀技术产出。后续还考虑将值班提醒,集成提醒,发布提醒做在工作台上。‍

‍研发环境与工程管理

研发环境 + 工程管理 解决的是如何快速进入本地开发的问题,如果是新人进入团队开发,从拿到电脑到进入开发,一般需要经历研发环境配置和工程环境配置这两个流程。

在这个过程中需要去各个地方翻阅文档,按照文档进行操作,在操作的过程中,还经常伴随着文档更新不及时,操作报错,出了错误又得去 Google 或者问身边的同事,整个过程费时又费力。

而 iBox 的研发环境和工程管理者两个功能模块则通过操作一键化来解决上述的问题。

首先是研发环境提供了 Flutter、Android、iOS 研发环境的检查和一键配置的功能,让不熟悉某个端的同学更加便捷的配置自己的研发环境,如下所示:‍

然后是工程管理提供了混合工程下 Flutter、Android、iOS 等壳工程环境环境检测,一键环境配置等功能,解决了环境配置复杂难以上手的问题,如下所示:

工程环境的复杂性在于它涉及 Flutter、Android、iOS 三个端的编译,编译的过程还会因为本地环境的差异而有所不同,各种编译报错,使得开发同学穷于应付。iBox 将从环境到工程的各种错误类型进行了梳理,并将错误信息展示出来,如下所示:

不仅让开发同学知道自己的工程环境有什么问题,还提供了对工程环境问题的一键修复,一键修复功能会先删除缓存(flutter clean,删除lock文件等),然后按照以下流程重新跑整个工程,确保可以修复工程环境,如下所示:

研发环境和工程管理这两个功能模块相互配合,真正解决了开发同学环境配置难的问题,同时它还打破了 Android 与 iOS 之间的门槛,让不熟悉另外一个端的同学也能进行这个端的调试和打包。

社区生态

集团内外针对 Flutter 都贡献了不少功能组件,但是并没有一个统一的地方展示这些组件,导致开发同学在需要用的时候,需要去 pub 库里各种搜索。

而 iBox 的社区生态功能提供了 Flutter 社区(集团内外)引擎、UI 组件、路由、动态化等各个方面的技术沉淀的展示,特别是 UI 组件,由于 iBox 本身就是基于 Flutter 开发的,那么这些 UI 组件的 Dart 代码可以直接在 iBox 上运行展示和交互,这种所见即所得的体验是非常棒的,如下所示:

变更单管理

在以前的开发流程中,Flutter 的研发流程是比较繁琐的,而且这些流程需要开发自己手工操作,如下所示:- 开始开发

而 iBox 的变更单功能,可以帮助 Flutter 研发同学快捷的完成研发流程的各种操作,如下所示:

这些一键式的操作不仅很好的提升了 Flutter 研发的效率,也规范了Flutter 的分支管理、集成方式,避免个人随意操作带来的工程问题。

以上便是 iBox 一期规划和完成的功能,它从根本上解决了上面提到的团队研发链路存在的种种问题,同时也感谢闲鱼同学在集成发布这块为我们提供的飞鱼工作台相关实践参考。

3 架构设计

iBox 在架构设计上主要关注以下几个问题:

通过对以上几个问题的思考,我们对 iBox 采取了纵向分层,横向模块化的设计,具体说来:

整体架构大图如下所示:

从上面的架构图可以看出辅助功能作为基础模块,为其他核心功能提供基础能力。接下来我们按照从工程到模块的顺序分别讲一下具体的设计方案:

工程结构

在整体工程上采用多仓库设计,之所以使用这样的设计,是因为 iBox 会涉及跨团队开发,多仓库可以让各个模块的源码彼此独立,不同模块之间不会相互干扰。

iBox 基于 git-repo 实现了多仓库的管理,仓库结构如下所示:

open-ibox git group
|-----------------------------------------------------------
|--- ibox
|--- ibox_common                               基础模块
|--- ibox_dashboard                             工作台
|---                                       ====== 研发 =====
|--- ibox_software                              研发环境
|--- ibox_project                               工程管理
|--- ibox_engine                                引擎管理
|--- ibox_community_ecology                     社区生态
|---                                       ====== 发布 =====
|--- ibox-app-size                               包大小
|--- ibox-change-order                           变更单
|---                                       ===== 工具箱 =====
|--- ibox-toolkit                              研发小工具

ibox 作为主工程,ibox_common 作为基础模块,其他模块都依赖于 ibox_common。开发 iBox 的同学只需要几行简单的命令,就可以同步 iBox 的全部源码工程。

mkdir open-ibox
cd open-box
git repo init -u http://xxx/open-ibox/manifest.git
git repo sync
git repo start --all master

然后在自己的模块进行开发和代码提交即可,彼此之间互不干扰。聊完了整体工程的设计,我们再来看看各个模块的设计。

模块设计

每个模块的核心功能在于处理UI交互与逻辑交互,不同于传统客户端的命令式 UI 框架,Flutter 采用的是声明式 UI 框架,驱动 UI 发生变化的是状态(State),如下所示:

图片引用自 Start thinking declaratively

Flutter 里的状态指的是在 Widget 之间或者内部存储和传递的数据或者信息,它可以分为短时状态和应用状态两种。

所以状态管理是编写 UI 和逻辑核心要面对的问题,它也会影响我们组织源码的方式,在 Flutter 状态管理的官方文档中,提供了 14 种状态管理方案,我们着重讨论官方比较推荐的前四种,至于其他的方案,感兴趣的可以去查阅官方文档。

我们先来看原生的两种状态管理方式:

setState 在应用场景上比较受限,InheritedWidget 对于开发者来说过于底层,使用起来比较复杂。既然官方的方案都有限制,我们再来看看社区提供的提供的比较推荐的方案。

事实上,Provider 和 Riverpod 的作者都是 Remi Rousselet,Riverpod 这个名字是 Provider 的字母重新排序后得到的,它的推出主要是为了解决 Provider 的一些功能缺陷,如下所示:

功能 Provider Riverpod
是否编译安全 存在运行时异常ProviderNotFoundException 编译时安全,在编译期间捕获错误,能编译就能正常运行。
是否对 provder 的编写和引用有限制 不支持同一类型的多个 provider 支持同一类型的多个 provider,也可以在任何地方编写和引用 provider。
是否依赖 Flutter 依赖于 Flutter 的 Widget。UI 代码和依赖注入耦合在一起。 不依赖 Flutter 的 Widget。可以独立的创建/共享/测试 provider,这也包括在可以在没有BuildContext的情况监听 provder。

基于以上的比较,我们最终选择了 Riverpod 这一套方案,并由此设计了模块的源码结构,如下所示:

iBox 模块源码结构
|-----------------------------------------------------------
|--- provider                             基于 Riverpod 实现的 State 管理方式(官方推荐)
|----- xxx.provider.dart                  provider
|--- service                              接口请求、数据处理相关实现
|----- xxx.service.dart                   service
|--- ui                                   页面与组件
|----- xxx.screen.dart                    页面

一个常见的编写 UI 逻辑的流程如下所示:

  1. 在 ui 部分编写页面和组件。
  2. 在 service 里编写和数据相关的逻辑。
  3. 在 provider 里编写相关 provider 类,它可以调用 service 里的功能。
  4. 在 ui 或者其他任何需要的位置引用 provider,操作相关逻辑。

这种方式实现了 UI 与逻辑的解耦和分离,UI 部分可以自由迭代,逻辑部分也实现了复用。

以上便是 iBox 的整体架构设计,相当于是一个简化版的插件化方案,如何后续有更丰富的插件生态进来,我们会考虑上架一个类似于 VSCode 的插件市场,不过目前对于我们来说,已经够用了。

插件化的设计使得可以自由组装各个模块,不同团队需要的模块功能不一样,我们推出了 app variant(变体)的功能。不同的 app variant(变体)拥有不同的 tab 栏配置,打包的时候就可以针对不团的团队打出不同功能的包。

4 上线效果

iBox 在研发链路核心痛点上使用前后对比

研发痛点 使用前 使用后
研发环境 + 工程环境 一般需要一天时间搭建好研发环境,后面的两三天时间折腾工程的各种编译问题。 实现了两个“一”,环境配置(Flutter)一小时完成,打包集成一键完成。
社区生态 组件比较分散,不知道有哪些组件可以使用,没有引导文档,也不知道该怎么使用。 在 iBox 上进行可视化展示,所见即所得,可进行交互操作,附带 Demo 代码,使用方法清晰明了。
引擎管理 全局引擎切换需要修改文件夹名或者 profile UI 界面一键切换,本地引擎版本统一管理。
变更单 需要跨两个平台,执行六步操作才能完成,手工操作还可能引发线上质量问题。 实现了集成步骤的 N 到 1,一键提交 Android 和 iOS 的双端集成。

iBox 用户在使用一段时间以后,也给了不少不错的反馈。

“一键安装还是非常好用的,帮开发节省了不少时间。以前各个地方下载,安装配置,还要解决版本冲突的问题,浪费不少时间。” “这次版本集成全走的iBox, 用着很爽。” “大幅简化了 Flutter 环境配置、集成繁琐等问题。”

此外,iBox 还处在一个刚起步的阶段,我们希望把它作为一款产品去迭代和运营。为此我们也为 iBox 设计了不同视角下的运维指标,如下所示:

全局视角:整体数据

用户视角:不同团队/个人偏好的功能

业务视角:做的比较好,受欢迎的功能

运维数据体系需要长期建设,它对我们后续的功能迭代和体验优化有着重要的指导意义,开发同学也是用户,只凭着拍脑袋想出来的功能,不一定能获得大家的认可。

四 技术总结

在做 iBox 之前,对于 Flutter 做过一些原理上的探究,之前整理编写了[《从架构到源码:一文了解Flutter渲染机制》] 一文,但是没有好的机会应用在生产实践上。这次的 iBox 开发之旅让我收获颇多,借着这个机会,我们就来聊一聊 Flutter Desktop 技术在生产实践上的应用。

1 Flutter Desktop 的发展历程

从2018年2月15日Flutter 团队发起的 flutter-desktop-embedding 项目到现在,已经四年过去了,中间的过程也是起起伏伏,从最初的不支持生产环境,到如今 Flutter 2.10 发布,正式宣布支持 Windows 平台生产环境 app 的开发,Flutter Desktop 的发展历程如下所示:

在 2022 年,Flutter 团队计划按照 Windows、Linux、MacOS 的顺序逐个推进,将对主流桌面端平台的支持带入到 stable channel,最终实现 Flutter "write once, run anywhere" 的愿景。

2 Flutter Desktop 的社区生态

和对 Android 和 iOS 的支持一样,Flutter 也实现了基于 Windows 等平台的 Embedder,Embedder 的上层是 C++ Engine 和 Dart Framework,它自己负责翻译和发送 Windows 等平台的消息。整体架构如下所示:

图片引用自 Announcing Flutter for Windows

点评:Linux、MacOS 等其他桌面端平台也是类似的实现结构,更深入的细节可以参见 platform 的实现。

移动端应用和桌面端的应用相比既有相同之处,例如:- GPU 图形加速

这也使得大部分现有的 Flutter 社区组件都可以在桌面端使用,但两者也有不同之处,例如:

基于这些不同,Flutter 针对桌面端平台也提供了针对性的支持,如下所示:

图片引用自 Announcing Flutter for Windows

在 iBox 的开发过程中,我们也使用了不少原生能力,这里针对 Flutter Desktop 常用的一些社区组件做个总结,如下所示:

现有的社区组件基本能满足我们的开发需求。

3 Flutter Desktop 的应用场景

iBox 是对 Flutter Desktop 技术的一次有意义的探索,它为我们的产品带来了更多的可能性,扩展了产品触达的边界。

那么,Flutter Desktop 适合哪些应用场景呢?

任何技术都有长短,Flutter Desktop 也有不适合的应用场景,如下所示:

当然技术也是不断发展的,当前存在的问题,也许在将来就被解决了。笔者对 Flutter Desktop 技术的发展还是很有信心的。

五 结语

Flutter 一份代码,在兼顾性能的同时上可以多端运行,是它的优势所在,解放了端上的生产力。尤其是对于 iOS 和 Android 同学比例严重失调的团队来说,这无疑是一个福音。

但是如果不注重 Flutter 开发周边配套工具的建设,从最开始的环境搭建、开发调试、再到集成发布没有好的工具去支撑,就很容易就演变成了 “Flutter 从入门到放弃”。这是因为业务团队和技术团队的诉求是不一样的,技术团队觉得解决 Flutter 各种问题的过程就是一个学习的过程,但是业务团队业务压力大,他们的第一诉求是快速开发,快速上线,如果周边配套工具缺失,他们很有可能就会选择放弃这个方案,这对于 Flutter 的推广是十分不利的。

我们希望刚接触 Flutter 的开发同学,他们的使用体验是平滑的,能一键完成的就一键完成,例如我们提出的“一小时完成 Flutter 环境搭建”、“一键配置/修复工程环境” 等等,这些理念也与 Flutter 团队最近发布的年度规划中的“提升开发者体验”不谋而合。

今年 2月10号,Flutter 团队发布了他们 2022 年的年度战略(Flutter 2022 Strategy)和路线 (Flutter 2022 Roadmap)。如下所示:

可以看到未来一年,Flutter 团队将开发者体验提到了非常重要的位置,他们将从 Flutter 的各个层面去改善开发者体验,例如:

上述提到的一些理念,例如 “让入门 Flutter 体验更加平滑,降低入门门槛”,和我们做 iBox 的初衷不谋而合。另外在 iBox 后续的规划中,我们除了降低开发同学的 Flutter 入门门槛,还希望降低新团队接入 Flutter 的成本。

现有的 Flutter 接入方案以混合工程方案 add Flutter to existing app 为主,这套官方提供的方案有着不小的接入、重构以及维护的成本,而且这是一个重复踩坑的过程,很多相同的问题会被不同的团队再次遇到,如果 iBox 可以提供一键接入的方案,那么将大大降低 Flutter 的接入和填坑成本,助力 Flutter 的推广。

Flutter 团队在年度战略(Flutter 2022 Strategy)中提到 “以用户(指 Flutter 开发者)为中心,其他一切都会随之而来”。

We believe in "focus on the user and all else will follow". This manifests in our emphasis on developer experience. 引用自 Flutter 2022 Strategy

相信在新的一年,Flutter 的研发体验会越来越好,iBox 也能为 Flutter 的推广尽一份绵薄之力。

六 参考资料

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8