混合开发工程化框架

2023-01-15 0 989

创作者 Deoria、张达理

背景

Flutter好处显而易见,缺点许多,一般来说他们在选择三个技术栈的时候一般来说会考虑虚拟化性,性能,塞里西,街道社区自然环境等因素,历经调研,Flutter满足用户以内大部份点,但在加进实际的业务情景中还须要他们历经一些产业化的构筑才能真正发挥出Flutter缺点,提升合作开发、正式发布等环节工作效率 所以他们在19年下半年迈入了Flutter产业化混和合作开发之旅。

今天主要撷取一下他们产业化构筑中的独立校对的预测设计、及Magpie Plugin混和合作开发构架的介绍。

现状预测及优化实践

flutter原⽣的合作Attichy, 它是三个比较的⿊盒的操作方式过程, 拿flutter fun那个较常⽤的功能为例:

dart标识符校对出乙醛,接着native工程建设软件系统校对乙醛, 校对装箱出app包再加装到电子设备中,接着透过attach命令相连到电子设备上。整座操作方式过程做了十分多的事情,也实现了破密的全屏操作方式,但那个⽅式不⼀定适合他们的需求。

主要难题有以下几个:

1. 网络连接成本低:官方的整座软件系统方式具有十分强的侵入性,有许多的自然配置文件,脚本和文件都被放在了工程建设之中,合作开发人员很难掌握大部份的细节。同时拿IOS比方说,那个操作方式过程是dart和iOS工程建设先后展开校对,把iOS和flutter的合作开发自然环境存取在了一起,事实上,iOS只须要flutter的函数库即可在app中运行flutter app。2. 自然环境连续性难题:由于邻近地区合作开发人员的自然环境各不相同,缺乏三个技术标准的合作开发、增容、正式发布自然环境,比如说加装的FlutterSDK版可能将不一样导致兼容性难题;比如说Android端构架兼容性难题;由此,他们须要技术标准合作开发人员的基础自然环境,做到受控,方便快捷网络连接。3. 职能不明确难题:现阶段native侧合作开发与dart侧合作开发业务流程及标识符Grignols谐振,比如说dart同学在合作测试阶段怎么方便快捷的与native端展开增容,而不须要三个工程建设展开类似软相连而带来的标识符上的强谐振。4. 可用性难题:现阶段存在的开放源码方案缺乏可方便快捷展开扩展、及动态注册登记解注册登记协议展开dart与native侧方法曾灿的支持以满足用户混和合作开发情景;缺乏三个建模的工具来方便快捷的展开电子设备相连、装箱、attach、正式发布等一套技术标准业务流程的操作方式。5. 合作开发工作效率难题:flutter fun那个操作方式过程是dart的标识符先校对,接着native标识符再校对,减慢了了他们在合作开发、增容整座操作方式过程中的工作效率;而且现阶段flutter fun那个操作方式过程中,默认会⽣生成debug、profile、release四种乙醛包,校对速度非常快,事实上他们可能将并不不须要大部份模式的乙醛。

基于以内这些难题,他们把整座业务流程从中间拆下,变成dart和native三个部分,然后透过magpie workflow再把他们串联起来。透过magpie workflow 的GUI增容dart标识符,接着透过magpie workflow校对dart标识符工业生产校对乙醛,再透过workflow正式发布; native侧透过远程依赖或者邻近地区依赖软件系统dart的校对乙醛,像平时一样校对增容和装箱。对于他们所处的实际的合作开发情景来讲,那个⽅方式对合作开发⼈员的角色定位更加的清晰,整座合作开发操作方式过程也更更加效率。

下面他们先来说一说Android在整座workflow中所做的一些工作:

1. Android端校对业务流程优化

拿Android来说,为了保持native视角合作开发网络连接简单易用,他们须要稍微改造下构建业务流程,让flutter自然环境在他们的SDK中展开依赖,这样native合作开发同学无需关心flutter自然环境难题,只须要简单软件系统magpieSDK。

1.1 构建乙醛

Flutter v1.12.13版更新对构建乙醛展开了分离,将flutter.jar和libflutter.so由aar依赖改为远程maven依赖,大大减小了flutter aar的大小的同时,也提升了build aar的工作效率

buildTypeengine乙醛可变乙醛debuglibflutter.soisolate_snapshot_data

vm_snapshot_data

kernel_blob.binreleaselibflutter.solibapp.so

1.2 难题预测

首先他们设想整座合作开发业务流程大概如下:

混合开发工程化框架

如果让Flutter和Native工程建设独立的方式去合作开发,那么Flutter module最后肯定是以aar的形式提供给Native工程建设依赖,这里须要考虑三个难题:

Native工程建设如何软件系统Flutter载体页?在Flutter 1.9.1版,Flutter engine被打入Flutter module aar中,Native端想要软件系统Flutter engine乙醛须要对Flutter module aar展开乙醛拆分工作,详情可参考Android Flutter 基于1.9.1版 构建预测及引擎拆分,但在1.12.13版中,Flutter将engine乙醛已经从Flutter module aar乙醛中剥离,改为用远程Maven仓形式提供给Native端,他们须要在给Native端提供的SDK中依赖那个Maven,即可实现Native工程建设软件系统载体页的工作。Flutter module在debug下如何增容?他们都知道在Flutter支持hot reload,那么如果让Flutter module独立合作开发,该怎么展开hot reload?答案是可以的,这里其实只要Native工程建设软件系统Flutter引擎相关的乙醛,接着在手机端加装上带有Flutter载体页的应用程序,打开Flutter载体页使用Flutter官方提供的命令flutter attach天然就可以支持hot reload功能,所以Flutter module独立合作开发debug模式下的增容功能不是难题。

1.3 具体实现

在magpie plugin的Android目录下的build.gradle中插入依赖flutter engine的任务即可实现在校对阶段展开引擎依赖:
apply from: “flutter_magpie.gradle”//软件系统flutter engine任务
在flutter_magpie.gradle中加入Flutter engine远程Maven依赖配置:
private static final String MAVEN_REPO =”https://dl.bintray.com/hxingood123/flutter/”;
在gradle.properties下设置引擎版号:
#引擎版 engineVersion=2994f7e1e682039464cb25e31a78b86a3c59b695
在flutter_magpie.gradle透过gradle脚本动态根据当前BuildType和
void addFlutterDependencies(buildType) { String flutterBuildMode = buildModeFor(buildType) if (!supportsBuildMode(flutterBuildMode)) { return } String repository = useLocalEngine() ? project.property(\local-engine-repo\) : MAVEN_REPO project.rootProject.allprojects { repositories { maven { url repository } } } // Add the embedding dependency. addApiDependencies(project, buildType.name, “io.flutter:flutter_embedding_$flutterBuildMode:$engineVersion”) List<String> platforms = getTargetPlatforms().collect() // Debug mode includes x86 and x64, which are commonly used in emulators. if (flutterBuildMode == “debug” && !useLocalEngine()) { platforms.add(“android-x86”) platforms.add(“android-x64”) } platforms.each { platform -> String arch = PLATFORM_ARCH_MAP[platform].replace(“-“, “_”) // Add the `libflutter.so` dependency. addApiDependencies(project, buildType.name, “io.flutter:${arch}_$flutterBuildMode:$engineVersion”) } }
最后将校对之后的aar及相关pom等文件上maven服务即可展开远程依赖,如果没有maven服务也可以直接展开aar邻近地区依赖

2. Android构架兼容方案

Android端校对须要考虑构架兼容合作开发,现阶段flutter装箱业务流程预设是不包含armabi构架,须要额外展开兼容处理。

将全构架引擎相关包上传maven,在flutter_magpie.gralde中展开动态依赖,合作开发这可以根据自己的项目展开选择行构架依赖,减少了邻近地区依赖的繁琐步骤。

依赖关系如下:

混合开发工程化框架

对于Flutter业务侧的armabi构架兼容,他们透过在点击workflow界面中的构建按钮之后的构建业务流程中的packFlutterAppAotTask任务中插入相关脚本将armeabi-v7a构架下的业务乙醛*.so文件move到armeabi构架下,这样就解决了Flutter侧业务乙醛的构架兼容性难题,关键标识符如下:

from(“${compileTask.intermediateDir}/armeabi-v7a”) {

include “*.so”

// Move `app.so` to `lib/<abi>/libapp.so`

rename { String filename ->

return “lib/armeabi/lib${filename}”

}

}

3. iOS端校对业务流程优化

整座校对业务流程,就是把dart的标识符校对为iOS工程建设中可用的产物,同时还附带了dart依赖的plugin的native标识符、plugin的注册登记器、Cocoapods的配置文件podspec以及快速软件系统到iOS工程建设用的脚本。

iOS工程建设使用校对的乙醛就可以透过Cocoapods直接软件系统flutter app。

3.1 构建乙醛

校对的乙醛如下:

App.frameworkisolate_snapshot_data 用于加速isolate启动,业务无关标识符,Debug模式独有vm_snapshot_data: 用于加速dart vm启动的乙醛,业务无关标识符,Debug模式独有kernel_blob.bin:业务标识符乙醛,Debug模式独有App 库文件Info.plist 库配置文件flutter_assets 资源和映射文件GeneratedPluginRegistrant.h 插件注册登记h文件GeneratedPluginRegistrant.m 插件注册登记m文件FlutterBusiness.podspec 业务和插件注册登记Cocoapod配置podhelper.rb Podfile生成脚本Plugins 插件目录Classes iOS源码Assets 资源A.podspec Cocoapod配置PluginA 插件APluginA 插件B…

3.2 难题预测

拆分flutterf官方的业务流程,许多步骤须要搞清楚原理,接着把每三个点还原出来,比如说:app.framework在不同自然环境下的生成,plugin的处理,Cocoapods的配置等。

3.3 具体实现

生成App.framework

App.framework即dart源码校对后的成品。根据校对模式的不同,在文件的细节上有差异。

Release模式

生成App库文件,在release模式下dart源码会校对为库文件。
flutter build aot –target-platform=ios
复制flutter自然环境下AppFrameworkInfo.plist得到Info.plist
/packages/flutter_tools/templates/app/ios.tmpl/Flutter/AppFrameworkInfo.plist
生成flutter_assets目录,在release模式下此目录中仅有字体和图片等资源
flutter build bundle –target-platform=ios
复制以内乙醛至App.framework

Debugs模式

生成App库文件,Debug模式下只有基础的API,不包含业务标识符
xcrun clang -x c arch_flags -dynamiclib -Xlinker -rpath -Xlinker \@executable_path/Frameworks\ -Xlinker -rpath -Xlinker \@loader_path/Frameworks\ -install_name \@rpath/App.framework/App\ -o “${derived_dir}/App.framework/App”
复制flutter自然环境下AppFrameworkInfo.plist得到Info.plist
/packages/flutter_tools/templates/app/ios.tmpl/Flutter/AppFrameworkInfo.plist
生成flutter_assets目录,Debug模式下包含业务乙醛kernel_blob.bin
flutter build bundle –debug
复制以内乙醛至App.framework

3.4 配置plugin

在合作开发dart时,不可避免的会加进一些plugin,这些plugin除了dart的源码外,还会有对应的iOS和android端标识符和依赖,须要软件系统到native工程建设中才可以保证flutter app在native正常的运行。

透过flutter提供的命令行可以下载dart依赖的package和plugin。

flutter pub get

在flutter pub get后,会在dart工程建设中生成三个.flutter-plugins文件,透过读取该文件,得到每个plugin名字和邻近地区路径。

battery=/Users/sac/flutter/.pub-cache/hosted/pub.dartlang.org/battery-0.3.1+7/ magpie=/Users/sac/magpie/ sqflite=/Users/sac/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.2.0/

透过路径可以找到每个plugin的目录,ios目录即plugin在ios端部分。

混合开发工程化框架

透过读取对应路径的目录下的pubspec.yaml,得到plugin在不同平台下的Class名称。

flutter: plugin: platforms: android: package: io.flutter.plugins.battery pluginClass: BatteryPlugin ios: pluginClass: FLTBatteryPlugin

iOS目录中包括源码、资源、podspec文件,复制各个plugin路径中的iOS目录至同三个Plugins目录中汇总。

plugin在native app中须要运行注册登记方法才可以使用,所以须要动态的生成注册登记方法。他们现在已经有了每个plugin的名称和Class名称,透过mustache模板生成文件即可。

GeneratedPluginRegistrant.h 固定内容写入GeneratedPluginRegistrant.m 使用mustache生成头文件导入和注册登记方法调用
#import “GeneratedPluginRegistrant.h” {{#plugins}} #if __has_include(<{{name}}/{{class}}.h>) #import <{{name}}/{{class}}.h> #else @import {{name}}; #endif {{/plugins}} @implementation GeneratedPluginRegistrant + (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry { {{#plugins}} [{{prefix}}{{class}} registerWithRegistrar:[registry registrarForPlugin:@”{{prefix}}{{class}}”]]; {{/plugins}} } @end

透过podspec配置了App.framework和plugin注册登记文件,须要在podspec中生成对各个plugin的依赖。透过mustache模板生成文件即可。

s.vendored_frameworks = \App.framework\ s.dependency \Flutter\ {{#plugins}} s.dependency \{{name}}\ {{/plugins}}

Cocoapods

整座乙醛里有多个podspec,他们提供了三个嵌入podfile的脚本,类似flutter官方做法,根据传入的参数生成FlutterBusiness和各个plugin的Cocoapod配置。

工具链支持

在dart侧他们为界面化工具合作开发了比如说:全屏校对装箱、attach、正式发布等常用合作开发业务流程中涉及到的功能。

workflow界面:

混合开发工程化框架
混合开发工程化框架

合作开发人员可以很方便快捷的透过以内这些界面化的操作方式展开展开校对、增容、正式发布的工作,大大减少了一些繁琐的命令执行操作方式过程,提高了可用性。

Magpie混和页面交互设计

对于混和页面跳转,他们看下面这张图:

混合开发工程化框架

FlutterView页面结构层级示意图:

混合开发工程化框架

显而易见,不处理的情况下的混和页面跳转:activity、FlutterView、Engine、isolate资源都是重新创建;那么这样会带来内存、资源重复、通信复杂等难题;Flutter官方也意识到了那个难题,在FlutterSDK1.12新版方已经支持Engine缓存。那么一般来说使用引擎缓存方案之后就变成如下图所示:

混合开发工程化框架

Magpiet通信设计

混合开发工程化框架

1. 基于业界成熟的方案,他们在混和栈的处理上使用了FlutterBoost的开放源码方案,不把时间花在重复的事情上。

2. Flutter的的dart侧与native侧的通信方式透过flutter plugin来实现。他们封装了通信的部分,在dart和native端都提供了可快速合作开发、⾼扩展性的功能实现接口。

3. 他们预先封装了一些基础通用能力,如果广播、日志、数据通信等通信功能

如何贡献&难题反馈

他们诚挚地希望合作开发人员提出宝贵的意见和建议,您可以在https://github.com/wuba/magpie_sdk阅读magpie_sdk项目源码、了解使用方法,可以透过提交PR或者Issue来反馈建议和难题。

总结及后续规划

现阶段他们主要是在Magpie混和合作开发产业化方面做了一些基础的构筑,那么接下来他们会从以下几个方面继续完善、深耕、探索。

1. flutter对app包的增量过⼤一直是三个令人诟病的难题,所以包大小的优化是接下来他们的重点。

2. 相比RN或者H5,Flutter唯一不足的地方就是业务动态化,现阶段业内也有一些思路可以借鉴,那么接下来此方向也是他们三个重点突破的方向。

3. 在此操作方式过程中,他们也希望能集思⼴益,借助街道社区的力量,如果有好的方案欢迎和他们一起讨论。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务