背景
这三个项目,开发周期都超过两年,很巧的是后端选型都不相同,web前端选型都不相同,移动端选型都不相同。
规模小的后端无所谓,大的能转基本上都转java了, web前端都在三驾马车范围内,相对可控。
这篇文章主要聚焦于这三个移动端项目中不同框架的优劣比较。
框架优劣
下表列出了五个不同框架的移动端项目在不同方面的表现,得分越高表示表现越好。这些分数谨代表个人看法。
| 原生开发 | webview + H5 | Cordova | React Native (RN) | Dart | |
|---|---|---|---|---|---|
| 交互性能 | 5 | 3 | 3 | 4 | 5 |
| 人力投入 | 3 | 5 | 4 | 4 | 4 |
| 调试效率 | 3 | 5 | 4 | 4 | 5 |
| 适配问题 | 5 | 3 | 3 | 3 | 4 |
| 方便更新 | 3 | 5 | 4 | 4 | 3 |
首先,框架选择应该根据项目性质来考虑:
- 如果项目对交互性能和流畅度要求较高,建议选择原生或Dart。
- 如果希望减少人力投入,或者需要强大的热更新支持,那么中间三个JavaScript框架可能更合适。
- 调试和适配问题通常不是主要问题,原生调试虽然不如H5和Dart方便。
- 适配问题通常在原生和Dart中相对较成熟,但Android设备和制造商的问题可能较多。
A项目
项目 A 是移动端项目,使用 Ionic 和 Cordova 封装早期版本的 AngularJS,支持 iOS 和 Android。
它的优势在于一套Web代码同时支持H5、iOS和Android,并支持热更新。然而,由于 Cordova 的生态系统,第三方提供的插件可能存在问题,无法满足需求,自行开发插件的灵活性也受到限制。尽管可以进行热更新,但发布和更新规则可能复杂,存在风险,回滚也是一个问题。
改造计划:
- 剥离原生的 Angular 运行环境,直接从远程加载编译后的HTML文件作为入口。这样将不再依赖Angular环境,为后续Web框架的重构提供更多选择,而且不再需要热更新,因为应用市场基本上都禁用了热更新。
- 剥离旧版本的 Cordova 壳,直接使用Webview,原生部分通过封装JSBridge接口调用。这样可以轻松集成原生代码。
- 转向使用 Dart + Webview 的方式,一些原生功能可以通过Dart插件实现,对于第三方插件无法满足的需求,可以自行封装或编写Bridge来与原生混编。
B项目
项目 B 使用 React Native 的早期版本 0.68,支持iOS和Android。
使其运行需要更改一些Xcode的编译配置和node_module的代码。适配问题比较多,依赖包都很旧,没有进行更新。业务主流程无法正常运行,代码量达到了10万行。
改造计划:
原生代码使用较少,主要依赖业务流程。未来更新频率不会很高,因此直接采用Dart启动重构计划。
C项目
项目 C 是一个Web H5改造项目,需要用到较多的原生能力的支持。
改造计划:
直接使用原生启动Webview,并实现JSBridge通道,需要高度原生能力的部分继续使用原生编写,只需封装一些调用方法和消息通道。
常规方案
如果要启动新项目,通常情况下,我建议首选Dart,原因如下:
- 一套业务代码支持双端。
- 性能与原生相当,交互体验也相当,编译后的应用文件自带Dart运行环境,LLVM编译后的字节码执行效率与原生差距很小。
- 开发和调试效率高,编写业务代码与JavaScript类似,具有热重载的调试功能,类似于Web调试。在调试时,JIT效率很高,编译后AOT性能也很好。
- 从我使用的几个框架来看,适配问题相对较少,社区也相对成熟。
如果项目需要使用H5的一部分业务,特别是需要频繁更新或与其他平台共享的业务,你可以在Dart中直接启动一个Webview,集成H5并与原生应用并存。一些原生能力可以通过市场上已成熟的插件满足,但如果不满足需求,你可以考虑自己编写插件,并定义好接口和参数,以满足双端底层模块的需求,然后封装并集成到应用中。
对于那些需要原生开发的部分,你可以采用混编的方式,无论是使用Kotlin、Java、Objective-C还是Swift,都可以编写原生功能,将其与应用集成。