在应用中升级 Capacitor 至 3.0
Capacitor 3 为生态系统带来了关键更新和激动人心的新特性。
在将应用升级至 Capacitor 3 后,您是否愿意在此讨论中分享您的反馈?我们非常乐意听取您的意见!💖
如果您是插件作者,希望将您的插件升级至更新的 Capacitor 版本,请参阅Capacitor 插件升级指南。
NodeJS 12+
Node 8 已结束生命周期支持。Node 10 将于 2021 年 4 月 30 日结束生命周期支持。Capacitor 3 要求 NodeJS 12 或更高版本。(推荐使用最新的 LTS 版本。)
Ionic CLI
如果您正在使用 Ionic CLI,官方对 Capacitor 3 的支持从版本 6.16.0 开始。我们建议通过 npm install -g @ionic/cli
升级至最新版本。
更新 Capacitor CLI 和核心库
npm install @capacitor/cli@latest-3 @capacitor/core@latest-3
ES2017+
Capacitor 3 现在构建面向 ES2017 环境,而非 ES5。插件模板也已更新以支持 ES2017,鼓励第三方插件更新其目标环境。
此更改不应影响您的应用,除非您需要支持 IE11,而 Capacitor 官方并不支持 IE11。
TypeScript 3.8+
Capacitor 3 使用了新的 TypeScript 语法,仅可在 TS 3.8 或更高版本中使用。
Capacitor 配置变更
如果您已安装 TypeScript 3.8+,您可以将 capacitor.config.json
迁移为类型化的 TypeScript 配置文件,命名为 capacitor.config.ts
。您可以继续使用 .json
文件,但 TypeScript 配置文件可能为您的团队提供更好的开发体验。以下是在 Capacitor 测试应用中使用的 capacitor.config.ts
文件示例。
/// <reference types="@capacitor/local-notifications" />
/// <reference types="@capacitor/push-notifications" />
/// <reference types="@capacitor/splash-screen" />
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.capacitorjs.app.testapp',
appName: 'capacitor-testapp',
webDir: 'build',
plugins: {
SplashScreen: {
launchAutoHide: false,
},
LocalNotifications: {
smallIcon: 'ic_stat_icon_config_sample',
iconColor: '#CE0B7C',
},
PushNotifications: {
presentationOptions: ['alert', 'sound'],
},
},
};
export default config;
官方插件
所有插件已从 Capacitor 核心库中移除,并放置到它们各自的 npm 包中。这样做有几个原因(参见 #3227),核心团队确信这是正确的方向。您可以像这样导入核心插件。
import { Camera } from '@capacitor/camera';
移除后台任务、权限和照片插件
- 后台任务:此插件似乎很少使用,且工作方式与大多数开发者的预期不太一致。核心团队将在未来重新审视后台功能。订阅 #3032 以获取更新。
- 权限:核心团队已实现了此集中式方法的替代方案,社区插件也可能采用(参见新的权限 API)。
- 照片:此未文档化的仅限 iOS 的插件已被移除。请使用
@capacitor-community/media
。
拆分辅助功能、应用和模态框插件
- 辅助功能
- VoiceOver 和 TalkBack 功能移至 屏幕阅读器
- 应用
- 模态框
迁移您的应用以使用新的官方插件包
此变更要求您单独安装您正在使用的每个插件。
- 在您的项目中搜索从
@capacitor/core
的Plugins
对象中提取的核心插件 - 查找相应的插件文档,注意某些插件已被拆分
- 按照文档中每个插件的安装说明进行操作
- 将插件导入更改为从插件的包中导入(参见插件导入)
- 遵循向后不兼容的插件变更中的任何说明
使用 Ionic Framework?
Ionic Framework 使用了以下插件中的 API:
为了获得与 Ionic Framework 的最佳用户体验,您应确保安装了这些插件,即使您没有在应用中导入它们:
npm install @capacitor/app @capacitor/haptics @capacitor/keyboard @capacitor/status-bar
插件导入
Plugins
对象已被弃用,但在 Capacitor 3 中将继续工作。Capacitor 插件应更新以使用新的插件注册 API(参见插件升级指南),这将允许它们直接从插件的包中导入。
今后,不应再使用来自 @capacitor/core
的 Plugins
对象。
// 旧方式
import { Plugins } from '@capacitor/core';
const { AnyPlugin } = Plugins;
首选直接从插件的包中导入插件,但插件必须更新以与 Capacitor 3 兼容才能实现这一点。
// 新方式
import { AnyPlugin } from 'any-plugin';
向后不兼容的插件变更
虽然许多插件 API 保持不变以简化迁移至 Capacitor 3 的过程,但一些 API 需要代码更新和手动迁移。
- 辅助功能 / 屏幕阅读器
isScreenReaderEnabled()
方法已重命名为isEnabled()
'accessibilityScreenReaderStateChange'
事件已重命名为'stateChange'
- 在 Android 和 iOS 上,
speak()
仅在屏幕阅读器当前激活时有效。对于屏幕阅读器激活或未激活时的文本转语音功能,请使用@capacitor-community/text-to-speech
。
- 浏览器
prefetch()
已被移除。
- 设备
- 应用信息已从
getInfo()
中移除(appVersion
、appBuild
、appId
和appName
)。请使用应用插件的getInfo()
获取此信息。 uuid
已从getInfo()
中移除。请使用新的getId()
函数。
- 应用信息已从
- 触觉反馈
HapticsNotificationType
枚举键已从大写转 换为驼峰式以匹配其他枚举。
- 本地通知
- 此插件现在使用新的权限 API。
requestPermission()
已被移除,请使用requestPermissions()
。
- 此插件现在使用新的权限 API。
- 推送通知
- 此插件现在使用新的权限 API。
requestPermission()
已被移除,请使用requestPermissions()
。
- 此插件现在使用新的权限 API。
- 分享
share()
方法现在返回ShareResult
而不是any
share()
的返回值将不再包含completed
。如果未完成,它将改为拒绝。
- 存储
- 需要数据迁移! 内部存储机制已更改,需要数据迁移。已添加一个便捷方法:
migrate()
。要在不影响最终用户的情况下更新您的应用,请在调用任何其他方法之前调用migrate()
。
- 需要数据迁移! 内部存储机制已更改,需要数据迁移。已添加一个便捷方法:
- 文件系统
stat()
方法现在在所有平台上以毫秒为单位返回 ctime 和 mtime 时间戳。以前,iOS 返回的时间戳以秒为单位。
日志记录变更
Capacitor 3 中已弃用 hideLogs
配置选项。它已被新的 loggingBehavior
配置选项替代。详情可在配置文档中找到。
iOS
Capacitor 3 支持 iOS 12+。需要 Xcode 12+。推荐使用 CocoaPods 1.8+。
更新 CocoaPods
建议将 CocoaPods 升级至最新稳定版本。CocoaPods 1.8 改为使用 CDN,这意味着不再需要定期运行 pod repo update
。
使用 pod --version
检查您的 CocoaPods 版本,并访问 cocoapods.org 获取安装说明。
将 iOS 部署目标设置为 12.0
为您的 Xcode 项目和应用程序目标执行以下操作:打开 Build Settings 标签页。在 Deployment 部分下,将 iOS Deployment Target 更改为 iOS 12.0。
然后,打开 ios/App/Podfile
并将 iOS 版本更新为 12.0:
-platform :ios, '11.0'
+platform :ios, '12.0'
use_frameworks!
将 Swift 版本设置为 5
如果您的应用尚未使用 Swift 5,请在 Xcode 目标中打开 Build Settings 标签页,然后在 Swift Compiler - Language 部分下将 Swift Language Version 更改为 Swift 5。
将 public
移至 iOS 目标目录
在 Capacitor 3 中,建议将 ios/App/public
目录移至 ios/App/App/public
。这可以在 Xcode 中实现:
移除现有 的 public
文件夹
- 展开
App
项目下的文件树,然后选择App
组,再选择public
文件夹。 - 右键单击 Delete。当提示删除文件夹或仅移除引用时,选择 Move to Trash。
在新位置重新创建 public
- 右键单击
App
项目内的App
组,然后单击 Add Files to "App"... - 保留默认选项(确保创建文件夹引用,而非组,并添加到
App
目标)。 - 单击 New Folder,命名为 "public"。
- 单击 Create,然后单击 Add。
在 Xcode 中可能看起来相同,但新的 public
文件夹现在应相对于 App
组,而非项目根目录。
gitignore 新的 public
文件夹
在 ios/.gitignore
中,将忽略路径从 App/public
更改为 App/App/public
。此文件夹包含您的 Web 资源副本,不应提交。
App/build
App/Pods
-App/public
+App/App/public
App/Podfile.lock
xcuserdata
更新 Capacitor iOS 平台
npm install @capacitor/ios@latest-3
npx cap sync ios
在应用程序事件中从 CAPBridge
切换到 ApplicationDelegateProxy
在 ios/App/App/AppDelegate.swift
中,更新以下内容:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
// Called when the app was launched with a url. Feel free to add additional processing here,
// but if you want the App API to support tracking app url opens, make sure to keep this call
- return CAPBridge.handleOpenUrl(url, options)
+ return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// Called when the app was launched with an activity, including Universal Links.
// Feel free to add additional processing here, but if you want the App API to support
// tracking app url opens, make sure to keep this call
- return CAPBridge.handleContinueActivity(userActivity, restorationHandler)
+ return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
}
移除 USE_PUSH 编译条件
如果使用推送通知功能,在 ios/App/App/AppDelegate.swift
中更新以下内容:
- #if USE_PUSH
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidRegisterForRemoteNotificationsWithDeviceToken.name()), object: deviceToken)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidFailToRegisterForRemoteNotificationsWithError.name()), object: error)
}
-#endif
如果不使用推送通知,您可以移除整个代码块
- #if USE_PUSH
-
- func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidRegisterForRemoteNotificationsWithDeviceToken.name()), object: deviceToken)
- }
-
- func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidFailToRegisterForRemoteNotificationsWithError.name()), object: error)
- }
-
-#endif
从硬编码的 CAPNotifications
切换到 NSNotification
扩展
在 ios/App/App/AppDelegate.swift
中,更新以下内容:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
let statusBarRect = UIApplication.shared.statusBarFrame
guard let touchPoint = event?.allTouches?.first?.location(in: self.window) else { return }
if statusBarRect.contains(touchPoint) {
- NotificationCenter.default.post(CAPBridge.statusBarTappedNotification)
+ NotificationCenter.default.post(name: .capacitorStatusBarTapped, object: nil)
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidRegisterForRemoteNotificationsWithDeviceToken.name()), object: deviceToken)
+ NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: deviceToken)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidFailToRegisterForRemoteNotificationsWithError.name()), object: error)
+ NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
}
忽略 DerivedData
将 DerivedData
添加到 ios/.gitignore
文件中。这是 Capacitor CLI 放置本地 iOS 构建的位置。
App/Pods
App/App/public
App/Podfile.lock
+DerivedData
xcuserdata
# Cordova plugins for Capacitor
Android
Capacitor 3 支持 Android 5+(并且现在支持 Android 11)。需要 Android Studio 4+。
更新 Capacitor Android 平台
npm install @capacitor/android@latest-3
npx cap sync android
切换到自动加载 Android 插件
在 Capacitor 3 中,首选自动加载 Android 插件 。在 MainActivity.java
中,可以移除 onCreate
方法。添加或移除通过 npm 安装的插件时,您不再需要编辑此文件。
public class MainActivity extends BridgeActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Initializes the Bridge
- this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
- // Additional plugins you've installed go here
- add(Plugin1.class);
- add(Plugin2.class);
- }});
- }
}
如果您的应用包含专门为您的应用程序构建的自定义插件,您仍然需要在 onCreate
中注册这些插件:
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ registerPlugin(PluginInMyApp.class);
}
}