一 前言
二 问题与挑战
1 问题
点评:从团队的调研采访来看,一个新人同学搭建 Flutter 的研发环境和工程环境,先需要一天时间搭建好基础环境,后面的两三天时间折腾各种编译问题,特别是 iOS 的相关环境对于 Android 同学来说想要完整跑起来十分费力。
点评:现有的 Flutter 模块集成流程分为六步:1 模块分支代码合并 -> 2 模块生成新Tag版本 -> 3 主工程修改模块版本号 -> 4 主工程代码合并 -> 5 主工程生成版本号 -> 6 摩天轮提交正式包打包,步骤繁琐,需要在 Aone、MTL 等平台来回切换,而且手工操作各种版本号,很容易引发线上质量问题。
2 挑战
-
接入和使用成本。研发工作台本来作为一款工具软件,它本身如果再操作复杂,需要看各种文档,那就背离了工具软件简单易用的初衷,所以复杂操作一键化是做相关功能时必须做到的,例如软件环境一键配置,工程环境一键配置,一键集成发布等,很多功能都是按照这个思路来做的。 -
兼容现有的研发环境和工程环境。除了新来的同学,大部分开发同学的电脑上已经有了部分环境,如何与现有的环境共存,不改变开发同学现有的使用习惯,也是我们重点考虑的问题。
三 技术全景
1 技术调研
-
业界:EasyBox,MBox 等工具。这些工具的核心一方面在于解决 Native 环境搭建,开发效率低的问题。另一方面深度封装 Git、Cocoapods,统一开发模式。
-
淘特:也有一些零散的脚本工具。但是整体上没有解决研发环境配置,开发调试,集成发布等问题。
-
面向前端的 Electron:使用 JavaScript、HTML 和 CSS 构建桌面端应用程序。
-
面向客户端的 Flutter Desktop:使用 Flutter 构建桌面端应用程序。
-
问题解决:Electron 和 Flutter Desktop 这两套方案都能解决我们的问题,虽然性能上有差异,但是这个不是我们最关注的点。
-
团队现状:客户端同学对 Flutter 熟悉,客户端同学的上手成本更低,不依赖其他端的人力。从这个角度来看,Flutter Desktop 会更好。
-
技术领域:Electron 和 Flutter Desktop 都在向前发展,Flutter 团队今年推出的 Flutter 2.10 将 Windows 平台正式带入稳定版本的支持,今年也会陆续完成 Linux、MacOS 等平台的稳定版本的支持。
-
业务趋势:工作台未来可能会向全平台扩展。例如在桌面端是一个研发工作台,在移动端(Android&iOS)iBox 是一个应用小工具集或者是一个类似于蚂蚁伙伴的app,在 Web 端是一个数据看板。从这个角度讲,Flutter Desktop 会更好。另外我们还想在工作台上做 UI 等组件的展示,如果基于 Flutter 来做,那么就能做到所见即所得,这会是一个非常好的体验,
2 功能设计
iBox 在功能设计上分为工作台、研发、发布、工具箱四大板块。其中研发、发布、工具箱又各自包含了很多子模块功能。
工作台
研发环境与工程管理
社区生态
而 iBox 的社区生态功能提供了 Flutter 社区(集团内外)引擎、UI 组件、路由、动态化等各个方面的技术沉淀的展示,特别是 UI 组件,由于 iBox 本身就是基于 Flutter 开发的,那么这些 UI 组件的 Dart 代码可以直接在 iBox 上运行展示和交互,这种所见即所得的体验是非常棒的,如下所示:
变更单管理
-
开始开发
-
创建Android摩天轮变更单 -
创建iOS摩天轮变更单 -
拉取变更分支 -
修改Flutter主工程的模块依赖代码 -
关联Aone需求
-
开发中
-
Android打包 -
iOS打包 -
提交模块代码CR -
本地源码依赖修改
-
完成开发
-
模块分支代码合并 -
模块生成新Tag版本 -
主工程修改模块版本号 -
主工程代码合并 -
主工程生成版本号 -
摩天轮提交正式包打包
-
开始开发:iBox 可以关联 Aone 需求一键创建变更单,同时创建新的变更分支,准备好当前变更所需的工程环境。
-
开发中:一键打 Android & iOS 双端包,一键提交变更仓库的 CR。
-
完成开发:一键提交集成,提交的过程中会自动完成上述的集成步骤。
3 架构设计
-
问题1:iBox 作为一款具备一定规模的 GUI 软件,如何方便且安全的组织各个功能模块的代码。
-
问题2:iBox 既然要面向共建,如何保证 iBox 自身的开发体验。
-
问题3:iBox 如何在保证共建开放的同时保证软件整体的质量和性能。
-
问题1:不同的功能进行模块化设计,模块源码彼此独立。这样可以精细控制源码仓库的权限,不同模块之间的修改不会相互影响。
-
问题2:基于 git repo 进行多仓库管理。既可以使用 git 操作单个的仓库,也可以使用 git repo 对多个仓库进行代码同步,代码提交,代码 Review 等操作,保障了 iBox 多仓库协同的开发体验。
-
问题3:
-
约定每个模块的基本架构设计。包括源码组织方式、状态管理方案等方面内容,并通过静态扫描来保障这些约定的落地。 -
限制三方库的引用以及指定三方库的版本(不使用^号来指定版本,例如:url_launcher: ^6.0.20)。^号指定的版本会导致后两位版本会自动升级(flutter upgrade 和 重新生成 pubspec.lock 文件的时候),导致打包的时候使用了一些意料之外的版本,引发质量问题(参考最近的 url_launcher 的 url_launcher_macos 自动升级导致链接打不开的问题 issue1 issue2 )。
-
首先是整体工程的设计。 -
然后是具体模块的设计。
工程结构
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 之间或者内部存储和传递的数据或者信息,它可以分为短时状态和应用状态两种。
-
短时状态(exphmeral state):也称为用户UI状态或者局部状态,是一个完全独立在 Widget 里的状态。Widget 树里的其他部分不需要访问这种状态,它也不需要使用状态架构架构(ScopedModel,Redux)去管理这种状态,它只需要一个 StatefulWidget 就可以了。
-
应用状态(app state):它是一个应用之间多个部分共享的一个非短时状态,并且用户在会话期间,保留这个状态。
-
setState -
InheritedWidget
-
Provider -
Riverpod
-
setState:通常用于处理 Widget 内部的短时状态。
-
InheritedWidget:setState 只能处理 Widget 内部的短时状态,如果需要处理应用状态,在 Widget 树之间进行通信,则需要用到 InheritedWidget,InheritedWidget 可以为其子孙节点提供数据和服务。
-
Provider:它对 InheritedWidget 组件进行了封装,使其更加易用,更易复用。
-
Riverpod:基于 Provider 改进而来,它是一个响应式的状态管理和依赖注入框架,编译安全,支持 DevTools 调试,本身不依赖于 Flutter。
|
|
|
|
|
|
|
|
|
|
|
|
iBox 模块源码结构
|-----------------------------------------------------------
|--- provider 基于 Riverpod 实现的 State 管理方式(官方推荐)
|----- xxx.provider.dart provider
|--- service 接口请求、数据处理相关实现
|----- xxx.service.dart service
|--- ui 页面与组件
|----- xxx.screen.dart 页面
一个常见的编写 UI 逻辑的流程如下所示:
在 ui 部分编写页面和组件。 在 service 里编写和数据相关的逻辑。 在 provider 里编写相关 provider 类,它可以调用 service 里的功能。 在 ui 或者其他任何需要的位置引用 provider,操作相关逻辑。 这种方式实现了 UI 与逻辑的解耦和分离,UI 部分可以自由迭代,逻辑部分也实现了复用。 以上便是 iBox 的整体架构设计,相当于是一个简化版的插件化方案,如何后续有更丰富的插件生态进来,我们会考虑上架一个类似于 VSCode 的插件市场,不过目前对于我们来说,已经够用了。 插件化的设计使得可以自由组装各个模块,不同团队需要的模块功能不一样,我们推出了 app variant(变体)的功能。不同的 app variant(变体)拥有不同的 tab 栏配置,打包的时候就可以针对不团的团队打出不同功能的包。 4 上线效果
iBox 在研发链路核心痛点上使用前后对比
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
“一键安装还是非常好用的,帮开发节省了不少时间。以前各个地方下载,安装配置,还要解决版本冲突的问题,浪费不少时间。” “这次版本集成全走的iBox, 用着很爽。” “大幅简化了 Flutter 环境配置、集成繁琐等问题。”
-
全站 PV -
全站 UV
-
覆盖的团队数 -
各个团队的用户覆盖率
-
访问量前10的用户 -
访问量前10的页面
-
团队 -> 功能模块 访问次数 -
个人 -> 功能模块 访问次数
-
最热功能模块排名
四 技术总结
1 Flutter Desktop 的发展历程
-
2018.02.15, 在 flutter-desktop-embedding 项目里提交第一个 initial commit。
-
2019.12.05,支持了 MacOS 平台。
-
2020.07.08,Linux 平台进入 alpha 阶段。
-
2020.09.24,Windows 平台进入 alpha 阶段。
-
2021.03.05,Flutter 2 正式发布,Flutter 对桌面端的支持进入稳定版本的前期准备阶段。
-
2022.02.15,Flutter 2.10 发布,Windows 平台率先进入稳定版本,可用于生产级 app 的研发,其他平台也在积极准备中。
2 Flutter Desktop 的社区生态
点评:Linux、MacOS 等其他桌面端平台也是类似的实现结构,更深入的细节可以参见 platform 的实现。
-
GPU 图形加速 -
渲染系统
-
动画 -
主题
-
文本输入 -
国际化
-
UI 组件
-
更大的屏幕尺寸 -
支持鼠标/键盘输入
-
输入法 -
导航方式
-
可访问性 -
系统独有的视觉样式
-
与底层系统的交互
3 Flutter Desktop 的应用场景
-
企业内部使用的工具类软件,尤其是在团队人员不足的时候,想快速落地一些工具和功能。
-
企业的ToB应用,例如收银台,饿了么商家端等。
-
团队自身已经有基于 Flutter 开发的移动端应用,想把部分功能扩展到桌面端。
-
对桌面端原生能力依赖较大的应用,因为针对桌面端的社区生态支持还还不如移动端这么完善,遇到缺乏的能力,需要自己去从零开始搭建。
五 结语
-
提升 DevTools 的易用性。
-
让 API 的使用体验更加平滑,逐步弃用和删除旧的 API。
-
修复 Hot Reload 有些时候不生效的问题。
-
让入门 Flutter 体验更加平滑,降低入门门槛。
We believe in "focus on the user and all else will follow". This manifests in our emphasis on developer experience. 引用自 Flutter 2022 Strategy
六 参考资料
-
macOS Performance Comparison: Flutter Desktop vs. Electron:https://getstream.io/blog/flutter-desktop-vs-electron/
-
List of state management approaches:https://docs.flutter.dev/development/data-and-backend/state-mgmt/options
-
riverpod:https://riverpod.dev/
-
provider:https://pub.dev/packages/provider
-
Announcing Flutter for Windows:https://medium.com/flutter/announcing-flutter-for-windows-6979d0d01fed
-
flutter-desktop-embedding:https://github.com/google/flutter-desktop-embedding
-
Start thinking declaratively:https://docs.flutter.dev/development/data-and-backend/state-mgmt/declarative
-
git-repo:https://git-repo.info/zh_cn/docs/getting-started/installation/
-
Announcing Flutter for Windows:https://git-repo.info/zh_cn/docs/getting-started/installation/
-
Flutter Desktop shells:https://github.com/flutter/flutter/wiki/Desktop-shells
-
Flutter 2022 Strategy:https://docs.google.com/document/d/e/2PACX-1vTI9X2XHN_IY8wDO4epQSD1CkRT8WDxf2CEExp5Ef4Id206UOMopkYqU73FvAnnYG6NAecNSDo9TaEO/pub
-
Add Flutter to existing app:https://docs.flutter.dev/development/add-to-app
ALL in one:如何搭建端到端可观测体系
点击阅读原文查看详情
文章评论