本文首发微信公众号:前端徐徐。
前言
随着移动设备的普及和用户需求的不断增长,APP开发已成为企业和开发者必不可少的一项技能。然而,面对纷繁复杂的开发技术和工具,选择最合适的开发方案常常令开发者感到困惑和不安。从原生开发到跨平台解决方案,再到现代的Web应用技术,每一种方案都有其独特的优势和适用场景。
为了帮助您在众多选择中找到最合适的路径,本篇文章将深入剖析当前最受欢迎的十种APP开发方案,包括传统的iOS和Android开发、跨平台的React Native和Flutter、现代化的CapacitorJS和PWA等。无论您是初涉移动开发领域的新手,还是希望优化现有开发流程的资深开发者,本文都将为您提供详尽的比较和实用的建议。
通过详细分析每个方案的优缺点及适用场景,希望能为您在开发过程中提供清晰的指导,帮助您做出明智的选择,进而实现高效、优质的APP开发。 请继续阅读,了解这十种开发方案的精髓,为您的开发之旅铺平道路。
1:iOS + Android + Webapp
- 三个代码库:需要分别为iOS(Swift)、Android(Kotlin)和Web(HTML+CSS+JS)维护独立的代码库,Web应用的代码在本地不重复使用。
- 技术栈要求:开发人员需要精通iOS的Swift、Android的Kotlin和Web的JavaScript。
- 招聘挑战:由于各平台的人才池较小,可能难以形成统一的技能基础,也增加了知识共享和团队协作的复杂度。
- 同步问题:维护和同步三个代码库可能具有挑战性,因为在不同平台实现功能的难度和开发效率可能不同。可能需要在某些平台(如iOS)上延迟发布功能,等待其他平台(如Android)的功能开发完成。不同平台的应用商店审核时间不同也会导致发布时的延迟。
- 本机优势:一旦发布,即可立即利用本机功能和用户体验改进,无需等待第三方实现。例如,本地先实现共享元素过渡,然后在Web上复制。
- 启动时间:由于无需加载React Native或CapacitorJS等第三方框架,应用启动时间可能更快。
2:React Native + React
- 两个代码库:需要分别维护React Native和React的代码库,但可“学习一次React”。
- Expo OTA/EAS更新:使用Expo OTA/EAS更新,可立即向所有客户端推送应用更新,无需等待App Store审查(对于大幅更改除外,如bug修复等,这些仍需要通过App Store审查)。
- 多平台支持:React Native不仅支持移动设备,还可运行在Windows、macOS甚至tvOS等其他平台上,符合React Native的多平台愿景。
- 性能优势:借助React Native的新Hermes引擎,应用启动时间可能快到小于1秒。
- 后续本机功能:需等待React Native对每个平台发布新本机功能的支持或自行实现,可能需要等待React Native构建的bug修复。特定于iOS或Android的新本机功能通常需要等到另一个平台提供相应功能的支持,才能实现跨平台利用。
- 单体存储库:可以在本地和Web代码库之间共享一些代码,如业务逻辑、状态管理、配置文件(翻译文件、TS类型、URL端点、货币转换等)、API调用、格式化请求/响应数据和身份认证。但通常不会共享UI渲染代码(样式、动画、导航),因为用户习惯会影响在不同平台上的外观和体验一致性。这可能导致在多平台使用或切换的用户体验出现不一致性。
- 灵活性/功能:不会受到Web标准化过程及其在各浏览器供应商中实现的限制,可依赖或等待React Native生态系统的库,或完全自主实现所需功能。
3. React Native for Web (RNW)
- 单一代码库:使用React Native Web(RNW),你可以"写一次React"并在多个平台上运行应用,即使不使用React Native引擎,而是简单地将React Native API转换为在Web上常用的react-dom API(如将
<View>
转换为<div>
)。 - 原生应用需求:如果用户最终需要原生应用,最好从一开始就不使用React Native Web,以避免后续的转换成本。
- 生态系统挑战:大部分React Native库并不一定支持Web开发,反之亦然。这可能导致在本地和Web上难以找到匹配的组件,并编写一致的包装组件。截至2022年10月,仅有166/1142个React Native包被官方支持为Web。React Native的库数量约占React生态系统的24%。截至2022年10月,React在NPM上有212,722个库,比React Native多出171,107个Web库。因此,如果计划仅部署到Web,使用纯React可能更为合适。
- 技术选型建议:传统上,React Native Web更适合单页应用(SPA),它使用CSS-in-JS的StyleSheet.create解决方案。但对于需要服务端渲染(SSR)以及响应式设计(通过CSS媒体查询),一些人可能会感到困扰。
- 解决方案推荐:推荐使用Tamagui来获得最佳体验和SSR兼容性。Tamagui将您的样式编译为CSS媒体查询,解决了上述问题,并提供了轻量级的原始样式系统和功能齐全的组件UI库。社区已经制作了tamagui-extras以提供更多组件。
- 导航/路由解决方案:推荐使用跨平台导航/路由解决方案如Solito(统一了react-navigation和nextjs/router)、react-native-url-router(使用React Router + react-native-screens + react-native-pager-view)或即将推出的Expo Router(基于expo-auto-navigation的概念验证/实验)。
- 折中方案:一种折中的方法是只使用RNW构建基本组件库(如按钮、标题、卡片等),而不共享导航/路由和样式。
- 手势交互:在浏览器中实现手势交互(如滑动)可能并不直接,因为使用CSS或JS的方法多种多样且质量参差不齐。由于React Native专为移动设备设计,它更适合处理手势交互。因此,可以考虑重用现有的React Native手势库。
4.Flutter
- 单一代码库:Flutter使得开发独立的iOS(Swift)和Android(Kotlin)原生应用的工作量减少至约一半。如果适用于您的用例,Flutter Web 可能仅需大约三分之一的工作量,因为它可以创建Web应用。
- 语言要求:必须学习Dart语言来开发Flutter应用。
- Flutter Web的适用性:Flutter团队自称,Flutter Web不适合面向内容/文档的应用或需要服务端渲染(SSR)和搜索引擎优化(SEO)的应用,因为它将所有内容渲染到单一的Canvas上。然而,对于跨平台游戏开发,Flutter与Flutter Web可能特别有用。
- 统一UI优化与平台差异:Flutter提供完全控制的渲染,虽然以牺牲特定于平台的功能和外观为代价,但通过优化实现了跨平台统一的用户界面。Flutter提供了Cupertino小部件来模拟iOS外观,同时使用Material UI小部件来支持Android外观。您还可以使用flutter_platform_widgets自动选择UI小部件的外观,根据运行平台(iOS或Android)进行适配。
- 原生UI创新和迭代:每个平台的新的原生UI功能可能会稍有延迟,因为它们需要在Flutter中重新实现。
- Flutter与其他框架的比较:在架构层面上,Flutter与React Native和原生iOS应用(Native)相比,提供了不同的混合应用开发方法。虽然Flutter和React Native都可以被视为混合开发的一种形式(因为它们不是纯原生的),但是“混合”一词通常用于描述通过Web View在原生外壳或封装应用中渲染Web应用的方法,这些方法通常只需一个代码库。
5. CapacitorJS + Webapp
- 原生API访问:CapacitorJS 提供了一个WebView,允许你访问原生API。
- UI外观:使用Ionic UI工具包,可以实现原生外观,或者选择Framework7来复制iOS和Android组件的样式。
- 框架选择:Web应用程序可以使用任何Web框架构建,如Solid、Vue、Svelte或Qwik。
- 原生插件:Capacitor支持使用NativeScript和NativeScript插件。
- 性能对比:与React Native的UX/性能对比,或者React Native与Ionic React+Capacitor的对比。
- 打包策略:Capacitor默认会将整个Web应用打包到App Store包中,以避免从Web加载,确保应用不会因缺乏原生功能而被拒绝。
- 即时更新:Ionic Appflow或Capgo可以解决App Store发布问题,实现近乎即时的代码更新。
6.Hotwire Turbo Native + Webapp
- 混合导航体验:结合原生导航和网络内容,实现混合原生和网页屏幕的无缝体验。
- 共享WebView:使用iOS的WKWebView和Android的WebView,实现跨平台的WebView重用。
- 框架兼容性:虽然Hotwire Turbo Native最初为Ruby on Rails开发,但也可与其他框架配合使用。
- HTML在线传输:通过HTML在线传输,简化开发流程,无需构建复杂的SPA和API,支持MPA方法或结合SPA+MPA的混合方法。
- Hotwire Strada:提供标准化的桥接,简化原生导航的实现。尽管原计划2021年发布,但因开发人员变动推迟至2022年,但即便没有Strada,Turbo Native仍可立即使用。
- 避免混淆:注意Hotwire的Turbo Native与React Native的Turbo Native模块架构、Turborepo构建系统或Turbopack打包工具不要混淆,它们各自服务于不同的技术栈和需求。
6.1 Turbo Native 搭配 iOS + Android shell
- 默认应用选择:Turbo Native 是使用 Hotwire Turbo 构建应用的默认选项。
- 原生外壳:Turbo Native 包含 turbo-ios 和 turbo-android,它们是为 iOS 和 Android 分别设计的外壳/包装应用。这些应用提供即开即用的体验,但在需要维护和调试 iOS 和 Android 开发时,可能需要额外处理。
- 导航模式限制:您必须自行处理自定义导航和过渡。
- 原生屏幕/功能:任何潜在的原生屏幕或功能都必须使用 Swift (iOS) 和 Kotlin (Android) 编写。
- 性能对比:与 React Native 外壳相比,使用这些特定的原生外壳(适用于 iOS 或 Android)可能会有更快的启动时间。
- 推荐演示:根据 Basecamp CTO DHH 的说法,Turbo Native for iOS 或 Turbo Native for Android 的演示是最佳的开始方式。
- 开发人员访谈:2021年8月2日,开发人员 Jay Ohms 主导的播客提供了关于整体方法的更多信息。
- SaaS 产品集成:如果您使用 Ruby on Rails 并且正在构建 SaaS 产品,Jumpstart Rails 似乎可以为您节省大量工作,并且价格合理,且与 Turbo Native 集成。2022年5月23日的播客采访提供了更多细节。
6.2 Turbo Native 搭配 React Native shell
- React Native Turbo 实现:通过使用 react-native-turbo,可以在 GitHub 上找到名为 react-native-turbo-demo 的示例。
- 工作原理:react-native-turbo-demo 提供了对 Turbo Native 工作原理的直观理解,如果你想在 React Native 中尝试实现类似功能,可以参考这个示例。
- 原生屏幕开发:允许使用 React Native 来编写原生屏幕,对于不想学习 iOS 和 Android 开发的 Web 开发人员来说,这非常有用。
7.React Native WebView
- 看似矛盾的选择:尽管听起来有些反常,但你可能会更倾向于采用 React Native Web。
- 快速移动端移植:如果你需要将现有的网络应用快速移植到移动端,特别是为了利用 iOS 推送通知功能(此功能于 2023 年 2 月 16 日发布,仅适用于 iOS 16 及以上版本的用户,且在 Safari 中暂不可用),这种方法可能非常有用。一些开发者通过这种方法取得了成功,避免了传统 React + React Native 方法所需的双倍代码库。
- 丰富的第三方包生态系统:与 Capacitor 等其他框架相比,React Native 的第三方包生态系统更为丰富,这可能是选择 React Native 作为外壳应用的原因。此外,将屏幕转换为 React Native 屏幕也相对容易。
- 部署优势:与通过 App Store 部署相比,这种方法可能有助于实现更快的部署流程。尽管对于仅使用 React Native (Web) 制作的应用,Expo OTA / EAS Update 也能实现快速部署,但你仍需关注这些工具的使用。
- App Store 审核风险:如果 React Native 外壳应用没有充分利用原生功能来增强 Web 应用,可能会面临 App Store 的审核拒绝。仅仅添加推送通知可能不足以被视为足够的原生功能。因此,保持谨慎并确保应用符合 App Store 的要求是明智的。
- 兼容性:此方法不仅适用于使用 React 制作的应用,还可以与任何 Web 框架或渲染库制作的 Web 应用一起使用。尽管在 React Native 外壳上工作时,React 可以实现一些知识的重用。
- 共享与重用:如果需要将应用重写为完全的 React Native 应用,使用 React Native 外壳可以加速这一过程。
- 通信桥接:react-native-react-bridge 是一个桥接工具,它简化了通过 WebView 在 React 和 React Native 之间的通信,或者你可以尝试通过直接在 WebView 和 React Native 组件之间运行彼此的函数来简化通信。
8.NativeScript + Webapp
- 原生平台支持:NativeScript 提供了 iOS 和 Android 的运行时环境。
- 原生 API 访问:通过 JavaScript 可以直接访问原生平台的 API。
- 声明式 UI:支持使用基于 XML 的语言和 CSS 子集来声明 UI。
- 跨平台应用构建:通常,开发者会构建一个 Web 应用,并通过以下方式实现跨平台:
- 使用 CapacitorJS 访问原生 API,将 Web 应用与 App Store 发布的应用捆绑,实现更快的启动速度。
- 制作 NativeScript 包装器/外壳应用,通过 NativeScript 的 WebView 渲染 Web 应用,便于更新但可能影响启动速度。
- NativeScript 与 Angular 和 Vue 集成,允许在不使用 WebView 的情况下实现代码共享。
- Web 上的 NativeScript:NativeScript 直接在 Web 上运行仍是一个待解决的问题。
- React NativeScript:提供了一种选择,允许使用 React 与 NativeScript 结合,适合那些希望为 React 编写原生模块但又不想使用 Swift/iOS 和 Kotlin/Android 的开发者。
- 成熟度和社区:NativeScript 在 2021 年 4 月 12 日时被认为还不够成熟,部分原因是生态系统中许多插件存在问题。一位早期和多产的贡献者在 2022 年 7 月 1 日离开了项目。社区规模相对较小,与 Flutter 或 React Native 相比,NativeScript 的贡献者数量较少。
9.Xamarin
- 代码共享:Xamarin Forms 允许在不同平台间共享高达98%的相同代码,这对于实现跨平台应用的开发非常高效。
- API 完整性:Xamarin Forms 提供了100%的API覆盖率,这意味着开发者可以访问所有原生平台的API,无需编写额外的本机包装器。
- 适合C#开发者:对于已经拥有C#开发人员和C#后端服务的企业来说,Xamarin Forms 提供了一个无缝的开发体验,因为它们可以利用现有的C#技能和资源。
10.PWA(渐进式Web应用程序)
- 移动设备访问:PWA 允许用户通过移动设备的主屏幕添加应用程序快捷方式,实现类似原生应用的访问体验。
- 跨平台能力:PWA 几乎可以在任何支持浏览器的平台上运行,但不使用原生组件,用户体验可能略逊于原生应用。
- Konsta UI:Konsta UI 提供了基于 Tailwind CSS 的移动组件,实现了 iOS 和 Android 设计风格,是 Ionic 的现代替代品。
- 潜在挑战:对于使用 SPA 架构并重新实现基本浏览器功能的 Web 应用,PWA 可能面临加载时间长、滚动体验差等问题,但这些问题可通过优化解决。
- 技术栈简化:PWA 通常使用 HTML、CSS 和 JavaScript 构建,简化了技术栈,减少了重复工作。
- 安装过程:PWA 不通过应用商店安装,用户可能需要引导才能将其添加到主屏幕,这可能需要额外的市场教育。
- 推送通知:PWA 在 iOS 上长期缺乏推送通知支持,但随着 iOS 16 的发布,苹果开始支持推送通知,为用户提供了一种新的通知方式。
- 渲染库选择:PWA 支持多种渲染库,如 React、Solid、Voby、Qwik、Vue、Svelte 等,开发者可以根据项目需求选择合适的库。
- 原生权限访问:现代浏览器为 Web 应用提供了广泛的原生权限访问,尽管仍有一些功能尚未实现。
- 桌面集成:PWA 可以通过 Electron 或 Tauri 等框架引入桌面环境,实现跨平台的桌面应用体验。
总结
根据具体使用情况和需求而定,对于很多使用场景来说,一个网页应用/PWA(渐进式网页应用)已经足够了。就像“如果你只需要一个网站,那就不要做应用程序!”一样,但如果你把你的应用程序构建为网页应用/PWA,用户最终通常会要求并期望有一个原生应用程序(这是一个大问题,因此要了解你的使用场景和用户)。与其和市场/用户争论和教育,不如选择他们已经熟悉的方式,这样更容易获得用户的认可。