SuperAPI AI 工具集

cordova-to-capacitor

编程与开发

查看项目

更新于 10-15 14:30

技能介绍

用途

本技能用于把 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 时出现;升级前应检查。

操作流程

  1. 审计(编辑前向用户报告):

    • 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 包装的代码。
  2. 在现有项目中安装 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)。

  1. 在首次发布前决定数据保留(scheme):参考 references/config-and-data.md。

  2. 执行 npm run build && npx cap add ios && npx cap add android。package.json dependencies 中列出的 Cordova 插件会安装到新的原生项目;已知不兼容的会被跳过并给出警告。

  3. 手动移植原生配置:用途字符串、权限、entitlements、URL schemes、方向、启动图/图标(npx @capacitor/assets generate)。参考 references/config-and-data.md。

  4. 逐个替换插件(references/plugin-mapping.md),把回调代码转为 Promise(references/code-patterns.md),执行 npx cap sync,每步后在设备上测试。

  5. 当没有依赖时移除 Cordova(见“移除”)。没有替代品的 Cordova 插件可保留,它们仍能工作。

  6. 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。