mcpField
C
capacitor-app-spm-migration

capacitor-app-spm-migration

github.com/capawesome-team开发52804 次安装1 周前更新
代码仓库

关于 capacitor-app-spm-migration

该技能指导将现有 Capacitor 应用的 iOS 依赖管理从 CocoaPods 迁移到 Swift Package Manager。它面向维护 Capacitor 6+ 应用的开发者,重点是重建 iOS 工程前备份并恢复用户文件、配置和插件。

主要功能

  1. 01迁移前检查项目与工作区状态
  2. 02盘点插件并备份自定义文件
  3. 03使用 SPM 重新生成 iOS 工程
  4. 04恢复签名配置并重新同步插件
  5. 05检查能力配置并验证构建

适用场景

  1. 01将现有 Capacitor 应用切换到 SPM
  2. 02迁移时保留 iOS 自定义代码与资源
  3. 03检查插件的 SPM 兼容情况
  4. 04迁移后验证签名和应用构建

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/capawesome-team/skills --skill capacitor-app-spm-migration

安装后在 Claude Code 中输入/capacitor-app-spm-migration确认已加载。

详细介绍

Capacitor 应用:从 CocoaPods 迁移到 SPM

将现有 Capacitor 应用项目的 iOS 依赖管理从 CocoaPods 迁移到 Swift Package Manager(SPM)。此迁移具有破坏性——现有的 ios/ 文件夹会被删除并重新生成,然后从临时备份中恢复用户编写的文件。

前置条件

要求版本
Capacitor6+
Node.js18+
Xcode15+
CocoaPods已安装(仅在删除前用于验证)

项目必须是 Capacitor 应用(而非插件),并且当前必须使用 CocoaPods(存在 ios/App/Podfile)。

流程

步骤 1:验证项目状态
  1. 验证项目是 Capacitor 应用,而非插件。确认 package.json 在 dependencies 中列出了 @capacitor/ios,且项目根目录包含一个 capacitor.config.* 文件。
  2. 验证项目当前使用 CocoaPods。文件 ios/App/Podfile 必须存在。如果该文件不存在,而 ios/App/CapApp-SPM/Package.swift 存在,则项目已使用 SPM——中止并告知用户。
  3. 从 package.json(dependencies 或 devDependencies)读取 @capacitor/core 版本。确认主版本为 6 或更高。如果低于此版本,则中止并先引导用户使用 capacitor-app-upgrades 技能。
  4. 验证工作树干净。运行 git status --porcelain——如果输出非空,指示用户在继续之前提交或暂存更改。此迁移具有破坏性,必须能够通过 git checkout 还原。
步骤 2:盘点已安装的 Capacitor 插件

读取 package.json,记录 dependencies 下安装的所有 Capacitor 插件。匹配以下前缀:

  • @capacitor/*(官方插件)
  • @capawesome/* 和 @capawesome-team/*
  • @capacitor-community/*
  • @capacitor-firebase/*
  • @capacitor-mlkit/*
  • @revenuecat/*
  • 其他任何在其 package.json 的 keywords 数组中包含 "capacitor" 的包

记录每个插件的包名和已安装版本。此列表将在步骤 8 中用于验证重新同步后所有插件是否都能通过 SPM 解析。

步骤 3:确定需要保留的文件

创建一份清单,列出 ios/ 中包含用户编写内容且必须在重新生成后保留的文件。检查以下每个路径是否存在,并且只记录存在的路径。

路径(相对于项目根目录)用途
ios/App/App/Info.plist应用权限、URL 方案、包配置、自定义键
ios/App/App/AppDelegate.swift自定义应用生命周期代码
ios/App/App/SceneDelegate.swift自定义场景生命周期代码(如果存在)
ios/App/App/Assets.xcassets/应用图标、启动屏幕资源、颜色集
ios/App/App/Base.lproj/LaunchScreen 和 Main 故事板
ios/App/App/App.entitlements推送、App Groups、关联域、Keychain Sharing
ios/App/App/GoogleService-Info.plistFirebase 配置(如果安装了 Firebase 插件)
ios/App/App/*.xcconfig构建配置覆盖项
ios/App/App.xcodeproj/project.pbxproj用于提取步骤 5 中签名值的源文件

此外,扫描 ios/App/App/,查找除 AppDelegate.swift 和 SceneDelegate.swift 以外的任何其他 .swift 文件。这些是用户编写的 Swift 源文件(例如,自定义 Notification Service Extension、自定义视图控制器),也必须保留。

如果项目包含 Notification Service Extension 或 ios/App/ 下的其他 Xcode 目标(例如 ios/App/NotificationService/),也记录这些目录。

步骤 4:备份保留的文件
  1. 创建备份目录:

    mkdir -p .spm-migration-backup
    
  2. 将 .spm-migration-backup/ 添加到 .gitignore,以防意外提交:

     # iOS files
    +.spm-migration-backup/
    
  3. 将步骤 3 中记录的每个文件复制到 .spm-migration-backup/,并保留相对路径。例如:

    mkdir -p .spm-migration-backup/ios/App/App
    cp ios/App/App/Info.plist .spm-migration-backup/ios/App/App/Info.plist
    cp ios/App/App/AppDelegate.swift .spm-migration-backup/ios/App/App/AppDelegate.swift
    cp -R ios/App/App/Assets.xcassets .spm-migration-backup/ios/App/App/Assets.xcassets
    cp -R ios/App/App/Base.lproj .spm-migration-backup/ios/App/App/Base.lproj
    

    对步骤 3 中识别出的每个文件/目录重复此操作。目录请使用 cp -R。

  4. 始终将完整的 ios/App/App.xcodeproj/project.pbxproj 复制到 .spm-migration-backup/ios/App/App.xcodeproj/project.pbxproj,尽管不会还原该文件本身。步骤 5 会读取它以提取签名值,步骤 11 可能会参考它重新配置功能。

步骤 5:提取签名和 Bundle 配置

读取 .spm-migration-backup/ios/App/App.xcodeproj/project.pbxproj,并从 App 目标的 XCBuildConfiguration 块(包括 Debug 和 Release)中提取以下构建设置的值。搜索每个键并记录其赋值:

  • PRODUCT_BUNDLE_IDENTIFIER
  • DEVELOPMENT_TEAM
  • CODE_SIGN_STYLE(例如 Automatic 或 Manual)
  • PROVISIONING_PROFILE_SPECIFIER(仅当 CODE_SIGN_STYLE = Manual 时)
  • CODE_SIGN_IDENTITY(仅当 CODE_SIGN_STYLE = Manual 时)
  • MARKETING_VERSION
  • CURRENT_PROJECT_VERSION
  • IPHONEOS_DEPLOYMENT_TARGET
  • SWIFT_VERSION

还要读取 .spm-migration-backup/ios/App/App/App.entitlements(如果存在),并记录功能列表。记录所有顶层键(例如 aps-environment、com.apple.security.application-groups、com.apple.developer.associated-domains)。

将提取的值保存在内存中,以便在步骤 9 中使用。

步骤 6:删除 ios/ 文件夹

向用户确认工作树已提交(必要时重新运行 git status --porcelain),并确认 .spm-migration-backup/ 包含步骤 3 中的所有文件。然后运行:

rm -rf ios
步骤 7:使用 SPM 重新生成 iOS 脚手架

运行:

npx cap add ios --packagemanager SPM

这会创建一个新的 ios/ 目录,其中包含基于 SPM 的脚手架。新结构包含 ios/App/CapApp-SPM/Package.swift,而非 ios/App/Podfile。

步骤 8:还原保留的文件

将备份的每个文件从 .spm-migration-backup/ 复制回 ios/ 下的原始路径,覆盖脚手架默认文件。例如:

cp .spm-migration-backup/ios/App/App/Info.plist ios/App/App/Info.plist
cp .spm-migration-backup/ios/App/App/AppDelegate.swift ios/App/App/AppDelegate.swift
cp -R .spm-migration-backup/ios/App/App/Assets.xcassets ios/App/App/Assets.xcassets
cp -R .spm-migration-backup/ios/App/App/Base.lproj ios/App/App/Base.lproj

对步骤 4 中备份的每个文件/目录重复此操作,但不包括 ios/App/App.xcodeproj/project.pbxproj——该文件不会还原。SPM 集成需要新的 project.pbxproj;旧文件中的签名值将在步骤 9 中重新应用。

如果新脚手架中不存在某个保留文件(例如 App.entitlements、GoogleService-Info.plist、自定义 Swift 文件),还必须在步骤 10 中将该文件添加到 Xcode 项目成员中。

步骤 9:重新应用签名和 Bundle 配置

编辑新的 ios/App/App.xcodeproj/project.pbxproj,并重新应用步骤 5 中提取的值。对于每项设置,在 App 目标的 XCBuildConfiguration 块中查找每个出现位置,并将脚手架生成的值替换为记录的值。

对每项设置应用此差异模式(以 PRODUCT_BUNDLE_IDENTIFIER 为例):

-				PRODUCT_BUNDLE_IDENTIFIER = com.example.app;
+				PRODUCT_BUNDLE_IDENTIFIER = <RECORDED_BUNDLE_ID>;

需要重新应用的设置(使用 replace_all 语义——更新 Debug 和 Release 配置中的所有出现位置):

  • PRODUCT_BUNDLE_IDENTIFIER
  • DEVELOPMENT_TEAM
  • CODE_SIGN_STYLE
  • PROVISIONING_PROFILE_SPECIFIER(仅适用于手动签名)
  • CODE_SIGN_IDENTITY(仅适用于手动签名)
  • MARKETING_VERSION
  • CURRENT_PROJECT_VERSION

如果记录的 IPHONEOS_DEPLOYMENT_TARGET 高于脚手架生成的值,则更新它。如果低于,则保留脚手架生成的值(新脚手架针对受支持的最低版本)。

步骤 10:将恢复的自定义文件添加到 Xcode 项目

新的 project.pbxproj 仅引用脚手架创建的文件。第 8 步恢复的文件中,凡是脚手架中不存在的文件(例如 App.entitlements、GoogleService-Info.plist、自定义 Swift 文件、Notification Service Extension 目标),虽然已存在于磁盘上,但在添加到项目的 PBXBuildFile、PBXFileReference 和 PBXGroup 条目之前,Xcode 中都不可见。

对于每个不属于脚手架的自定义文件,告知用户在 Xcode 中执行以下一次性操作(SPM 脚手架没有 App.xcworkspace,请直接打开 App.xcodeproj):

  1. 打开项目:npx cap open ios(或 open ios/App/App.xcodeproj)。
  2. 在 Xcode 项目导航器中,右键点击 App 组,然后选择 Add Files to "App"…。
  3. 选择每个恢复的自定义文件(例如 App.entitlements、GoogleService-Info.plist、自定义 .swift 文件)。
  4. 确保 Copy items if needed 未勾选,并且 App 目标已勾选。

对于 App.entitlements 文件,还需在 ios/App/App.xcodeproj/project.pbxproj 中设置 CODE_SIGN_ENTITLEMENTS 构建设置。将此差异模式同时应用于 App 目标的 Debug 和 Release XCBuildConfiguration 块:

 				CODE_SIGN_STYLE = Automatic;
+				CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
 				CURRENT_PROJECT_VERSION = 1;

如果项目还有其他 Xcode 目标(例如 ios/App/NotificationService/ 下的 Notification Service Extension),用户必须在 Xcode 中重新创建这些目标。SPM 脚手架不会重新生成非 App 目标。请明确告知用户。

步骤 11:重新配置功能

对于第 5 步中从 App.entitlements 记录的每个功能键,请确认 Xcode 中已启用对应功能:

  1. 通过 npx cap open ios 打开 ios/App/App.xcodeproj。
  2. 选择 App 目标 → Signing & Capabilities 标签页。
  3. 对于每个 entitlement 键,通过 + Capability 按钮添加匹配的功能:
    • aps-environment → Push Notifications
    • com.apple.security.application-groups → App Groups
    • com.apple.developer.associated-domains → Associated Domains
    • keychain-access-groups → Keychain Sharing
    • com.apple.developer.in-app-payments → Apple Pay
    • com.apple.developer.icloud-services → iCloud

这是唯一需要与 Xcode 交互的步骤。请明确告知用户必须手动完成此步骤。

步骤 12:重新同步插件

运行:

npm install
npx cap sync ios

npx cap sync ios 会更新 ios/App/CapApp-SPM/Package.swift,以包含第 2 步中记录的所有 Capacitor 插件。留意警告——此处会报告任何不支持 SPM 的插件。

如果报告某个插件与 SPM 不兼容,请告知用户。用户必须选择以下操作之一:

  • 等待插件维护者提供上游 SPM 支持,或
  • Fork 该插件,并使用 capacitor-plugin-spm-support skill 添加 SPM 支持,或
  • 从项目中移除该插件。
步骤 13:验证构建
  1. 在 Xcode 中打开项目并解析 SPM 包:

    npx cap open ios
    

    在 Xcode 中选择 File → Packages → Resolve Package Versions(或等待打开时自动解析)。

  2. 从命令行构建模拟器版本,确认所有内容均可编译:

    npx cap run ios
    
  3. 确认应用可以启动,且之前正常运行的功能(推送通知、深层链接、Firebase 等)仍然可用。

步骤 14:清理

构建验证通过且应用正常运行后:

  1. 删除备份目录:

    rm -rf .spm-migration-backup
    
  2. 从 .gitignore 中移除 .spm-migration-backup/ 条目。

  3. 确认没有残留 CocoaPods 产物:

    find ios -name 'Podfile*' -o -name 'Pods' -o -name '*.xcworkspace'
    

    如果有任何结果,请将其删除。SPM 工作流直接使用 App.xcodeproj——不存在 App.xcworkspace。

  4. 提交迁移:

    git add -A
    git commit -m "chore(ios): migrate from CocoaPods to Swift Package Manager"
    

错误处理

  • npx cap add ios --packagemanager SPM 失败并提示 "ios platform already exists" — 第 6 步未完成。重新运行 rm -rf ios,然后重试。
  • npx cap sync ios 报告某个插件不支持 SPM — 在该插件提供 Package.swift 之前,无法在 SPM 下使用它。告知用户并暂停迁移;不要悄悄移除该插件。
  • 构建失败并提示 "Module 'X' not found" — 插件的 SPM 包尚未解析。在 Xcode 中运行 File → Packages → Reset Package Caches,然后运行 File → Packages → Resolve Package Versions。
  • 构建因代码签名错误而失败 — 第 9 步重新应用的值缺失或不正确。重新读取 .spm-migration-backup/ios/App/App.xcodeproj/project.pbxproj,并确认已将 DEVELOPMENT_TEAM 和 PRODUCT_BUNDLE_IDENTIFIER 应用于 Debug 和 Release 两种配置。
  • 迁移后推送通知停止工作 — 第 11 步未重新添加 Push Notifications 功能,或者 App.entitlements 未通过 CODE_SIGN_ENTITLEMENTS 关联(第 10 步)。
  • Firebase 已初始化,但没有数据显示 — GoogleService-Info.plist 已恢复到磁盘,但在第 10 步中未添加到 Xcode 项目的目标成员资格中。
  • 缺少自定义 Notification Service Extension 目标 — npx cap add ios 不会重新生成非 App 目标。请在 Xcode 中手动重新创建该目标,并重新添加其源文件。
  • 用户表示想要回退 — 由于第 1 步已确认工作树干净,可以使用 git checkout -- .,然后运行 git clean -fd ios .spm-migration-backup 撤销整个迁移。

相关技能

  • capacitor-plugin-spm-support — 用于为 Capacitor 插件(而非应用)添加 SPM 支持。如果第 12 步报告某个插件不支持 SPM,且用户拥有该插件的源代码,请使用此技能。
  • capacitor-plugins — 用于在迁移后安装或重新配置 Capacitor 插件。
  • capacitor-app-upgrades — 如果项目使用 Capacitor 5 或更早版本,请先使用此技能将其升级到 Capacitor 6+,然后再返回此处。
  • capacitor-app-development — 用于迁移后的 Capacitor 应用开发常见主题、故障排除和最佳实践。

评论

支持 Markdown