跳到主要内容
版本:v7

将应用中的 Capacitor 升级至 3.0

Capacitor 3 为生态系统带来了重要更新和激动人心的新功能。

阅读 Capacitor 3.0 发布公告 ›

升级应用至 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 使用了仅支持 TS 3.8 及更高版本的新 TypeScript 语法。

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

拆分的辅助功能、应用和模态插件

  • 辅助功能
  • 应用
    • 应用相关信息和功能保留在 应用
    • 应用 URL 处理(openUrl()canOpenUrl())移至 应用启动器
  • 模态
    • 操作表功能(showActions())移至 操作表
    • 对话框功能(alert()prompt()confirm())移至 对话框

迁移应用到新版官方插件包

此变更要求您单独安装每个正在使用的插件。

  1. 在项目中搜索从 @capacitor/corePlugins 对象中提取的核心插件
  2. 查找对应的插件文档,注意部分插件已被拆分
  3. 按照文档中的安装说明操作每个插件
  4. 将插件导入改为从插件包导入(参见插件导入
  5. 遵循向后不兼容的插件变更中的指导

使用 Ionic 框架?

Ionic 框架使用了以下插件的 API:

为获得 Ionic 框架的最佳用户体验,即使应用中未直接导入这些插件,也应确保它们已安装:

npm install @capacitor/app @capacitor/haptics @capacitor/keyboard @capacitor/status-bar

插件导入

Plugins 对象已被弃用,但在 Capacitor 3 中仍可工作。Capacitor 插件应更新至使用新的插件注册 API(参见插件升级指南),这将允许直接从插件包导入插件。

今后不应再使用来自 @capacitor/corePlugins 对象。

// 旧方式
import { Plugins } from '@capacitor/core';
const { AnyPlugin } = Plugins;

推荐直接从插件包导入插件,但该插件必须先升级以兼容 Capacitor 3。

// 新方式
import { AnyPlugin } from 'any-plugin';

向后不兼容的插件变更

虽然许多插件 API 保持不变以简化迁移过程,但部分插件需要代码更新和手动迁移。

  • 辅助功能 / 屏幕阅读器
    • isScreenReaderEnabled() 方法重命名为 isEnabled()
    • 'accessibilityScreenReaderStateChange' 事件重命名为 'stateChange'
    • 在 Android 和 iOS 上,speak() 仅当屏幕阅读器激活时有效。如需在屏幕阅读器无论激活与否都能进行文本转语音,请使用 @capacitor-community/text-to-speech
  • 浏览器
    • 移除了 prefetch()
  • 设备
    • getInfo() 移除了应用信息(appVersionappBuildappIdappName)。请使用 App 插件的 getInfo() 获取这些信息。
    • getInfo() 移除了 uuid。请使用新的 getId() 函数。
  • 触觉反馈
    • HapticsNotificationType 枚举键从大写改为驼峰式以匹配其他枚举。
  • 本地通知
    • 此插件现在使用新版权限 API。移除了 requestPermission(),请使用 requestPermissions()
  • 推送通知
    • 此插件现在使用新版权限 API。移除了 requestPermission(),请使用 requestPermissions()
  • 分享
    • 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 文件夹

  1. 展开 App 项目下的文件树,选择 App 组中的 public 文件夹
  2. 右键点击 Delete。当询问是删除文件夹还是仅移除引用时,选择 Move to Trash

删除 public 文件夹

在新位置重建 public

  1. 右键点击 App 项目内的 App 组,选择 Add Files to "App"...
  2. 保留默认选项(确保创建文件夹引用而非组,并添加到 App 目标)
  3. 点击 New Folder,命名为 "public"
  4. 依次点击 CreateAdd

重建 public 文件夹

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 {
// 当应用通过 URL 启动时调用。可在此添加额外处理,
// 但如果希望 App API 支持跟踪应用 URL 打开,请确保保留此调用
- 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 {
// 当应用通过活动(包括通用链接)启动时调用
// 可在此添加额外处理,但如果希望 App API 支持
// 跟踪应用 URL 打开,请确保保留此调用
- 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);
-
- // 初始化 Bridge
- this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
- // 已安装的额外插件在此添加
- add(Plugin1.class);
- add(Plugin2.class);
- }});
- }
}

若应用包含专为您的应用构建的自定义插件,仍需在 onCreate 中注册这些插件:

 public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

+ registerPlugin(PluginInMyApp.class);
}
}

更新 Gradle 至 7.0

现推荐在 Capacitor 项目中使用 Gradle 7