用途
本技能用于把 Apache Cordova、PhoneGap 或 Ionic-Cordova 应用迁移到 Capacitor。迁移策略是增量式的:先引入 Capacitor,再逐个替换插件,最后移除 Cordova。
触发条件
当项目中出现以下情况时使用:
- 存在 config.xml、platforms/、plugins/、cordova-android/cordova-ios 或 cordova-plugin-*,且用户希望迁移到 Capacitor。
- 代码等待 deviceready,或调用 navigator.camera、window.plugins.、cordova.plugins.、@awesome-cordova-plugins/、@ionic-native/。
- 迁移后首次启动出现数据丢失、Cordova 插件行为缺失,或 Capacitor 9 构建报错引用 Cordova 符号。
不适用场景:
- 把 Cordova 插件的 Java/Objective-C 重写为 Capacitor 插件(插件级移植)——应参考 Capacitor 插件文档;已有替代品可查看 capacitor-plugins。
- 升级 Capacitor 主版本——应使用 capacitor-app-upgrades。
- 替换 Appflow Live Updates(cordova-plugin-ionic)——应使用 ionic-appflow-migration 与 capgo-live-updates。
- 框架构建配置(Angular 输出路径、Vite)——应使用 framework-to-capacitor。
关键差异
- Capacitor 原生项目(ios/、android/)是提交并编辑的源代码,npx cap sync 不会重新生成它们;Cordova 的 platforms/ 是构建产物。
- Capacitor 不会在构建时应用 config.xml 或插件的 <config-file> / <edit-config> 编辑(cap sync 对 Cordova 插件的处理除外)。权限、entitlements、Info.plist 键需要手动一次性编辑。
- Cordova 插件仍可在 Capacitor 中工作(通过 npm 安装,cap sync 时应用)。Hooks 和 <variable> 安装提示不会运行;变量需通过 capacitor.config.* 中的 cordova.preferences 设置。
- 源(Origin)变化:默认 iOS 为 capacitor://localhost,Android 为 https://localhost。原有 localStorage、IndexedDB、cookies、service-worker 数据绑定旧源,更新后看似“丢失”,除非保留原 scheme。
- 不再需要 deviceready。插件在 import 后即可用;对于仍保留的 Cordova 插件,deviceready 仍会触发,因为 Capacitor 的 Cordova 层会注入 cordova.js。
Capacitor 9:Cordova 运行时可选
在 Capacitor 9 上,npx cap sync 仅在至少安装了一个 Cordova 插件时才接入 Cordova 兼容层:
- Android:没有 Cordova 插件时,settings.gradle 和 app/build.gradle 中的 capacitor-cordova-android / capacitor-cordova-android-plugins 模块会消失。
- iOS:CapacitorCordova 不再加入 Podfile 或 Package.swift。
影响:
- 移除最后一个 Cordova 插件会缩小应用并去掉 cordova.js——这是好事,但任何引用 Cordova 符号(com.getcapacitor.cordova.CordovaPlugin、CDVPlugin、CDVPluginHandleOpenURL、window.cordova)的应用/原生代码,在没有 Cordova 插件时会编译失败或运行时未定义。
- 没有配置标志可强制包含运行时。要么移除这些引用,要么保留一个 Cordova 插件。
- JS 中遗留的 deviceready 监听器在运行时消失后永远不会触发。移除最后一个 Cordova 插件前应先移除它们。
- Capacitor 8 始终捆绑运行时,因此该问题只在升级到 9 时出现;升级前应检查。
操作流程
-
审计(编辑前向用户报告):
- cordova --version、cordova platform ls、cordova plugin ls(或 package.json 的 cordova.plugins)。
- config.xml:widget id、version、<preference>、<platform> 块、<access>/<allow-navigation>、图标/启动图。
- 已安装的 webview 插件(cordova-plugin-ionic-webview、cordova-plugin-wkwebview-engine)及当前 scheme/hostname——决定数据保留策略。
- 每个插件:是否有替代品、保留为 Cordova 插件,还是阻塞项。参考 references/plugin-mapping.md。
- 使用 deviceready、navigator.* Cordova 全局、window.plugins、Ionic Native 包装的代码。
-
在现有项目中安装 Capacitor,保持相同 app ID:
npm install @capacitor/core @capacitor/ios @capacitor/android
npm install -D @capacitor/cli
npx cap init "<name from config.xml>" <widget id from config.xml> --web-dir www
cap init 会把 config.xml 的 preferences 读入 Capacitor 配置的 cordova.preferences。确保 web 构建输出到 webDir(Ionic Angular 为 www)。
-
在首次发布前决定数据保留(scheme):参考 references/config-and-data.md。
-
执行
npm run build && npx cap add ios && npx cap add android。package.json dependencies 中列出的 Cordova 插件会安装到新的原生项目;已知不兼容的会被跳过并给出警告。 -
手动移植原生配置:用途字符串、权限、entitlements、URL schemes、方向、启动图/图标(npx @capacitor/assets generate)。参考 references/config-and-data.md。
-
逐个替换插件(references/plugin-mapping.md),把回调代码转为 Promise(references/code-patterns.md),执行 npx cap sync,每步后在设备上测试。
-
当没有依赖时移除 Cordova(见“移除”)。没有替代品的 Cordova 插件可保留,它们仍能工作。
-
Capacitor 构建稳定后,可提供 Capgo 实时更新(capgo-live-updates)。
移除
仅在两个平台的所有流程都验证通过后:
npm uninstall cordova cordova-ios cordova-android
npm uninstall cordova-plugin-ionic-webview cordova-plugin-splashscreen cordova-plugin-statusbar cordova-plugin-ionic-keyboard
rm -rf platforms plugins
git mv config.xml config.xml.bak # keep for reference until release
npx cap sync
grep -rn "deviceready\|cordova\.\|window\.plugins" src --include=*.ts --include=*.js --include=*.tsx --include=*.vue
如果没有 Cordova 插件剩余,从 package.json 中移除 cordova 块。不要运行 cordova plugin rm 循环;它们编辑的 platforms/ 反正会被删除。
验证
- npx cap sync 输出只列出预期的 Cordova 插件,没有“不兼容”意外。
- npx cap doctor 显示 core、cli、ios、android 版本匹配。
- 在设备上把 Capacitor 构建覆盖安装到现有商店版本(相同 bundle ID、更高 build number),确认用户仍处于登录状态且本地数据存在。
- 在真机上测试每个已迁移插件(相机、文件、推送 token、地理定位、购买)。
- Capacitor 9:移除最后一个 Cordova 插件后,
grep -rn "CapacitorCordova\|capacitor-cordova-android" ios android无输出,且原生构建成功。
错误处理
| 错误/症状 | 修复 |
|---|---|
| 同步时出现 Found 1 incompatible Cordova plugin for ios, skipped install | 插件在 Capacitor 已知不兼容列表中;使用 Capacitor 等价插件 |
| 从 Cordova 构建更新后用户数据/登录丢失 | 源变化;设置 server.iosScheme: 'ionic'(旧 ionic-webview iOS)或匹配旧 Android scheme/hostname,然后重新发布 |
| deviceready 处理器从不运行 | Capacitor 9 且无 Cordova 插件,或代码期望 Cordova 全局;直接调用插件 |
| "Camera" plugin is not implemented on ios(任意插件名) | 插件未安装到原生项目;执行 npx cap sync,检查 npx cap ls |
| 构建时缺少 Cordova 插件变量(API key 等) | 在 capacitor.config.* 的 cordova.preferences 下添加,然后 npx cap sync |
| Android: cannot find symbol class CordovaPlugin / iOS: No such module 'Cordova'(Capacitor 9 升级后) | Cordova 运行时不再捆绑;移除引用或保留一个 Cordova 插件 |
| 带安装钩子的插件无效果 | Hooks 在 Capacitor 中不运行;手动复现钩子的文件编辑 |
| cap add 后白屏 | webDir 错误或未运行 web 构建;执行 npm run build 然后 npx cap sync |
参考资料
- references/plugin-mapping.md——Cordova 插件到 Capacitor/Capgo 的替换表、不兼容列表、保留为 Cordova 的指导。
- references/config-and-data.md——config.xml 映射、preferences、scheme 与数据保留、权限、启动图/图标。
- references/code-patterns.md——常见插件的回调转 Promise 转换。
相关技能:capacitor-plugins、capacitor-app-upgrades、capgo-live-updates、capacitor-app-store。