笔者的感概: 从现在的趋势看,App 开发者未来究竟会是终端工程师,而终端工程师要会的技能除了要了解各端开发完成外,更重要的是具备串联各端、各言语的能力。

引言

去年写了篇文章,讲了下笔者了解的跨端东西链是什么样的。

在补齐跨端通讯能力(GNB)后,整套东西链在稿定终端开发中已经是一个成熟体系了,能够体系的来介绍下咱们在其间是做了些什么,是怎样落地的。

相关文章

《说到跨端东西链,咱们是在说什么?》

《跨端通讯终结者|看我是怎么确保多端消息一致性的》

能力概览

跨端东西链是一个抽象概念,意图是把端与端的联系经过东西链条联系起来。

在具体完成上,咱们是落在终端服务层(application-services),从物理架构上看,它便是一个独立的 git 库房。

跨端工具链,在稿定终端研发中的实践

包含生成服务、终端组件、开发辅佐扩展三个部分。

跨端工具链,在稿定终端研发中的实践

那咱们怎么来了解终端服务层

咱们结合 DevOps 的概念来看,终端服务其实是在 Dev 前置一步的环节中,为了开发服务的一层,往往是在构建前或许构建进程中参与编译运用。

生成服务

生成服务(codegen)类似工厂车间,它能够依照标准输入,依靠固定模板,生成标准输出的各终端产品。

想了解具体生成进程的,能够看这篇文章:从零开始|构建 Flutter 多引擎渲染组件:跨端东西链篇

东西言语选型上,前期多运用 Ruby 言语,原因是为了开发运用方便,究竟公司内部都是用 Mac 开发,MacOS 内置了 Ruby 环境,没有什么预装置本钱,合适前期探索落地。后续,考虑到与打包机、Dock 容器等环境保持一致,所以逐步迁移成 Python 来开发。

无论是什么言语开发,都会添加 shell 文件main.sh来确保运用进口的一致性。Flutter 组件化东西以及跨端通讯协议还会添加preview.sh来生成 markdown 预览文档。

在标准输入上,也会根据实际需求有一些差异,由于数据来历是不一致的,有些服务需求读取服务端接口,有些自闭环的能够写在生成服务本身,还有一些能够写在各个项目中,经过必定标准即可让东西读取到。

那在产品输出上也有差异,有些是作为文件直接生成到项意图模块中,功能上相对独立的会生成产品 SDK,作为终端组件

终端组件

但凡能够打包成 SDK 的,究竟会被打包成 SDK。

咱们在前期东西链规划上,产品尽量是一个独立的终端组件,以轻量为主。意图便是在后续稳定时能够提供独立的 cocoapods / gradle / npm / pub / … 组件库,乃至是提供二进制库的方法来削减构建本钱。

在组件人物上,现在是划分的比较清晰:调用组件/支撑组件。望文生义,比如 GNB 消息通讯能力在 iOS / Android / 桌面端是支撑组件完成,而 Web / Flutter 是调用组件完成。

但这也不是肯定的,比如后续 Rust 加入进来,那 Rust 侧便是支撑组件的方法,而其他代码侧则是构建调用组件。也比如或许也会让 Flutter 来支撑 Web 开发。

在运用上,只需项目集成就能够具备相应的跨端能力,抹平各个渠道差异性。

组件 SDK 化的另一个优点是调用 API 是不变的,对于上层事务来说不关心是怎么完成的,SDK 怎么变化,也无需改变事务代码,更改生成模版代码即可。

开发辅佐扩展

可自动化的究竟会自动化,可 AI 完成的究竟会让咱们赋闲[狗头]。

什么是开发辅佐扩展? 提高开发效率,下降人为因素导致的意外问题的东西。咱们更想把它了解成稿定终端 IDE的前身,现在是在VS Code上初步建设了Web & App Flutter & App 两个开发辅佐扩展,用于把整个跨端开发构建流程自动化起来,削减开发同学心智本钱,让开发只关心一端代码即可。

后续演变上,IDE建设便是把项目、运转终端设备、开发辅佐扩展三者结合起来,让 Web / Flutter 工程直接在 App 项目中上构建运转调试。

开发参考:构建 VS Code Extension,提高 Flutter 开发效率(一)

落地方法

前面是介绍咱们在稿定终端开发中跨端东西链都做了什么,也用终端服务层(application-services) 的方法把它们结合在一起。

但其实有一个非常重要问题,怎么把终端服务层(application-services) 落地到具体的各个项目中,这问题的实质是在多个库房代码怎么有机的结合在一起。

这个问题也有许多种解法,笔者逐个列出,然后讲一下咱们的最佳实践。

计划选型

二方库/三方库

构建完成后组件上传到内部库房(二方库)或许上传到 github / npmjs / pub / ..(三方库),当作独立组件来运用。

按理说这算是终究形状,但假如改动频频就涉及到发包的问题、事务项目也要频频的修正包版别号,对小范围内部开发来讲不友好。并且每个组件都需求独立一个版别号,版别号办理起来本钱也非常大,比如发包前就要查看各个组件的版别清单。

Git 子模块(submodule)

Git 对于复杂多项目也提供了一个解决计划,运用 submodule 子模块的方法,把组件作为一个独立的库房加入到事务库房中。

看起来很契合咱们的需求,但它的问题是自身存在许多缺点,这儿不搬运其他文章过来了,有兴趣的能够在搜一下 git submodule 的坑。

咱们的最佳实践

最后咱们运用的这个方法姑且称作脚本库房办理,市面上的确没有人说有这么做,但作用的确意外的好。

到底是个什么样的计划?

一句话描绘:各终端库房经过添加脚本代码setup_application_services.sh,自行经过各个言语环境的东西链,集成到项目构建进程中。

setup_application_services.sh

# 链接应用服务
#!/bin/sh
VERSION=0.1.1 # 运用的版别号,后续解说作用
CURPATH=$(
  cd "$(dirname "$0")"
  pwd
)
cd $CURPATH
DIRECTORY=../application-services # as 服务下载位置,建议放到项目根目录
if [ ! -d "$DIRECTORY" ]; then
    git clone git@git.gaoding.com:gdmobile/application-services.git $DIRECTORY
fi
cd $DIRECTORY
git clean -f
git reset --hard
git remote update origin
git checkout $VERSION
git pull origin $VERSION
cd ..

具体讲一下这个脚本的作用:

  • 直接把application-services库房下载到工程内部,作为一个完整的子文件夹。
  • 清理掉或许被开发操作的库房改动。
  • 拉取该分支下最新的代码。

这样来确保每次履行脚本,都能够取得一个契合版别预期的正确库房内容。

VESION常量实质上是指定git branch分支号,只不过咱们生成名称为版别号的分支来完成的更高雅。(在开发测验中,笔者都是新增开发分支VERSION=dev/xxxx来做)

这种方法带来的优点:

  • 版别号能够统一办理。
  • 确保开发环境的干净,每次履行脚本都会还原一些意外的误改动。
  • 可当作普通组件修正测验,只需不履行脚本,就能够直接修正其间代码来验证问题。

仅有的害处是拉取的是整个库房,跟工程无关的代码也会被拉取下来,但这是可接受的,对于开发而言只是硬盘多占用一些,在开发进程中不受影响。

各端落地方法

稿定在各端项目上都是采用 Monorepo 多项目大仓办理的模式,所以咱们需求的也是把application-services中的组件也当作它的一个项目,这样来抹平开发的认知本钱。

也不能让开发同学手动去调用脚本,这样也太不高雅了,咱们还需求把它融入到整个集成流程中。

下面分开讲下不同的工程咱们都是怎么做的(划重点)。

iOS

iOS 需求在 Pod 之前提早履行application-services.sh

首先需求在Podfile中最前面添加模块引入。

跨端工具链,在稿定终端研发中的实践

这样让 Pod 履行前先去履行manager.rb文件。

跨端工具链,在稿定终端研发中的实践

manager.rb 中要害代码:

# 拉取最新的 application-services
def setup_application_services
  Pod::UI.puts "check git application-services".green
  system File.join($PROJECT_PATH, "tools", "setup_application_services.sh")
end

在履行pod install / pod update时,就会先去履行setup_application_services.sh脚本。

跨端工具链,在稿定终端研发中的实践

然后是怎么运用大仓模式呢?

这儿推荐大家两个 Ruby 插件:cocoapods-monorepo 、cocoapods-headermap,用于大仓办理的,这都开源在 RubyGems(前同事留下的成果 ~)。

这儿添加application-services下载后的文件夹索引路径即可。

跨端工具链,在稿定终端研发中的实践

但开源版别只支撑传单个 path,需求进行一些扩展改造,建议下载插件源码到本地来运用。

Android

Android 比较简单些,只需新增一个 Gradle 履行文件即可。

application_services.gradle

task Setup(type: Exec) {
    exec {
        commandLine rootDir.getParentFile().getParent() + '/tools/setup_application_services.sh'
    }
}

而 Monorepo 公司 Android 是采用的手动指定,但也完全能够经过一个 Gradle 来遍历查询。

Flutter

Flutter 比较费事一点,由于flutter pub get流程并不合适做钩子,所以咱们采用了另一种方法,利用 VS Code ExtensionFlutter 开发辅佐东西添加指令来帮助开发把这个流程自动化。

跨端工具链,在稿定终端研发中的实践

Monorepo 也是经过手动指定依靠路径。

Web

Web 脚手架比较完善,很容易集成进去。

跨端工具链,在稿定终端研发中的实践

scripts 添加一下调用即可。

而 Monorepo 前端就更成熟了,咱们运用 pnpm 的大仓计划即可。

pnpm-workspace.yaml

packages:
  - "src/*"
  - "../application_services/*"

总结

当时的跨端东西链建设只是开始,当下在稿定内部也逐步推广起来,慢慢分散到各个团队中去运用,未来上还是有更多的或许性。


感谢阅读,假如对你有用请点个赞 ❤️

跨端工具链,在稿定终端研发中的实践