跳过主要内容

如何修复一个 Capacitor 插件 (Bun, npm, pnpm)

How to patch a Capacitor plugin with bun patch, patch-package or pnpm patch, apply native iOS and Android fixes, and decide when to fork or upstream.

文章来源

马丁·多纳迪厄

作者

瓦莱里亚

审阅者

乔丹

编辑

如何修复一个Capacitor插件(Bun、npm、pnpm)

要修复一个 Capacitor 插件,请编辑插件的文件 node_modules,保存更改为 bun patch --commit (或 patch-package 在 npm 和 Yarn 上, pnpm patch-commit 在 pnpm) 中,生成的文件请在 patches/然后运行 bunx cap sync 所以本地项目可以接收到它。包管理器在每次安装时重新应用补丁,适用于您的团队和 CI。

补丁是正确的选择,当插件有一个小 bug、一个阻止构建的版本约束或一个已合并但未发布的上游修复时。该指南涵盖了每个包管理器的工作流程、如何将本地补丁传递到 Xcode 和 Gradle,以及何时使用分叉或上游 PR 是更好的选择。

为什么补丁适用于本地插件 code

一个 Capacitor 插件是 npm 包含三个部分: dist/在 Android 中修复 code android/,并且在 Android 和 iOS code 中 ios/ 在 Package.swift.Capacitor 直接编译原生部分 node_modules:

  • Android: android/capacitor.settings.gradle includes 每个插件的 android 文件夹 node_modules.
  • iOS 使用 CocoaPods在 Podfile 中,各个插件都被引用为 :path => '../../node_modules/...'.
  • iOS(使用SPM): CapApp-SPM/Package.swift 在 Capgo 中,参考每个插件的本地路径 node_modules.

一个对 Capgo 的更改 node_modules/@scope/plugin/ios/Sources/... 在您的应用程序二进制文件中 cap sync 并且需要重新构建。无需发布。

在您修补之前

  1. 检查更新。 查看插件的变更日志和打开 PR。升级比补丁更好。
  2. 阅读许可协议。 MIT 和 Apache-2.0 允许私人修改。Copyleft 许可证,如 GPL 或 MPL-2.0 可能要求您在发布应用程序时发布修改过的源代码。检查之前发布。
  3. 写下原因。 在提交消息中输入问题 URL 或一行原因。六个月后,谁也不会记得原因。 patches/ 有一个文件在里面。

使用 Bun 进行补丁。

Bun 内置了补丁功能。无需额外的包,无需脚本。 postinstall script.

# 1. Prepare the package for editing
bun patch @capacitor/haptics

# 2. Edit files under node_modules/@capacitor/haptics

# 3. Save the patch
bun patch --commit node_modules/@capacitor/haptics

Step 1 makes Bun give you a private copy of the package in node_modules,所以编辑不会影响Bun的全局缓存。步骤3写入差异并将其记录在 package.json:

{
  "patchedDependencies": {
    "@capacitor/haptics@8.0.2": "patches/@capacitor%2Fhaptics@8.0.2.patch"
  }
}

提交两次 package.json 同时提交和 patches/ 文件夹。 每个 bun install包括 bun install --frozen-lockfile 在 CI 中,应用补丁。

关键包含的确切版本。如果您升级插件,Bun 不再匹配补丁,因此为新版本重新创建它或删除它,如果修复已发布。

使用 npm 或 Yarn:patch-package 补丁

npm install --save-dev patch-package

添加一个 postinstall 脚本以便补丁在每次安装后应用:

{
  "scripts": {
    "postinstall": "patch-package"
  }
}

然后编辑文件夹中的 node_modules 并生成补丁:

npx patch-package @capacitor/haptics

这将 patches/@capacitor+haptics+8.0.2.patch。提交它。如果补丁在升级后停止应用 patch-package 将安装失败并显示明确的消息。

Yarn Berry有自己的 yarn patch <pkg> / yarn patch-commit -s <path> 流程来存储补丁在 resolutions 字段中。

修补使用 pnpm

pnpm patch @capacitor/haptics
# edit the temporary folder pnpm prints
pnpm patch-commit <path-printed-above>

pnpm记录补丁在 patchedDependencies 并在安装时应用。

示例:修复插件中的native build错误

常见情况:您的应用程序使用AGP 9,一个较旧的插件 android/build.gradle 仍然引用 proguard-android.txt,AGP 9拒绝。您不能等待发布。

bun patch some-capacitor-plugin

编辑 node_modules/some-capacitor-plugin/android/build.gradle:

 buildTypes {
     release {
         minifyEnabled false
-        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
     }
 }

保存并同步:

bun patch --commit node_modules/some-capacitor-plugin
bunx cap sync android
cd android && ./gradlew assembleDebug

本错误的详细信息在 修复 Capacitor 插件构建错误(使用 AGP 9).

示例:放松 iOS 依赖约束

Two plugins pin different versions of the same SDK and CocoaPods can’t resolve them. If you’ve verified the plugin works with the newer SDK, relax its podspec:

-  s.dependency 'FirebaseMessaging', '11.15.0'
+  s.dependency 'FirebaseMessaging', '>= 11.15.0', '< 13.0'

示例:放松 iOS 依赖约束 Package.swift:

-  .package(url: "https://github.com/firebase/firebase-ios-sdk.git", exact: "11.15.0")
+  .package(url: "https://github.com/firebase/firebase-ios-sdk.git", "11.15.0"..<"13.0.0")

Then:

bunx cap sync ios

对于 SPM 应用程序,这个约束位于插件的 cd ios/App && pod update FirebaseMessaging 然后: Podfile.lock 使用 CocoaPods 可能需要 一次,因为 在 Xcode 中。

修补Capacitor核心

有时问题出在 @capacitor/android, @capacitor/ios 或是CLI,修复方案则在上游pull请求中。您可以使用相同的方式修复这些包,但每个团队都需要维护相同的差异。

Capgo发布了 @capgo/capacitor-patch 为此。它是一个只包含hook的包,包含了一个小型版本锁定的修复方案,修复方案会链接回上游的PR。它不会执行任何操作,直到您选择启用它:

bun add @capgo/capacitor-patch
bunx capgo-capacitor-patch list --all
import type { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.example.app',
  appName: 'Example',
  webDir: 'dist',
  plugins: {
    CapacitorPatch: {
      patches: ['upstream-pr-8418-android'],
      strict: true,
    },
  },
};

export default config;

修复包在 cap sync 和 cap updatecontext bunx capgo-capacitor-patch doctor HTML text fragment from a longer Capgo UI string (parent key `compare_step_capacitor_text`). Page/area: Capgo marketing website. Role: Website copy sentence. Seen in: page alternatives/expo.astro, page alternatives/median.astro. Message key `compare_step_capacitor_text` (Compare Step Capacitor Text). | Page/area: Capgo marketing website. Role: Short UI label or navigation item. Seen in: page trust.astro. Message key `and` (And). strict: true修复包之后,原生项目修复包才会执行。 会进行一次dry run。通过 ,当选定的修复方案不再适用时,同步会失败,这会告诉您升级后修复方案是否过时。请参阅

插件文档

情况 最佳选择
几行代码,已合并到上游 修补,下次发布后删除
版本约束太严格 修补,开一个上游问题
尚未上游修复的bug 修补并发送一个相同diff的PR
新功能或大规模重构 分叉,发布在你的范围内
插件已被弃用 分叉,或者切换到一个维护的插件

分叉好

如果你分叉了,发布它,以便安装保持可复现:

# in the fork, rename to your scope in package.json: "@acme/capacitor-foo"
bun run build
bun publish --access restricted

从 Git URL 安装也行,但插件的 dist/ 文件夹必须在该 branch 中存在或由脚本构建,并且并非每个包管理器都默认运行依赖项生命周期脚本。发布的包避免了这个问题。 prepare 请记住,__CAPGO_KEEP_0__ 名称会改变原生模块名称,__CAPGO_KEEP_1__ 生成的 SPM (

记住,npm 的名称会改变原生模块名称,CLI 生成的 SPM 会使用这个名称。@acme/capacitor-foo ),所以更新分叉的 AcmeCapacitorFoo以匹配。详细信息在 Package.swift 迁移一个__CAPGO_KEEP_0__插件到SPM 将一个 Capacitor 插件迁移到 SPM.

__CAPGO_KEEP_0__插件目录 Capgo.可能已经存在一个维护的插件来覆盖它。

上游

目标是删除您的补丁。打开一个最小的可复制问题,包括您的Capacitor和插件版本,以及补丁差异。然后打开一个PR。维护者比单独的问题报告更快地合并小的、经过测试的修复。

补丁和实时更新

您的Web包包括插件的JavaScript代码 dist/,因此对JS侧的补丁将随着下一个Web构建一起发布。使用 Capgo实时更新 来

到达不需要商店发布的用户。 Package.swift only take effect in a new native build submitted to the stores. Don’t push a web bundle that depends on a native patch to users who still run the old binary. Capgo’s 的更改只在提交到商店的新原生构建中生效。不要将依赖于原生补丁的Web包推送给仍然运行旧二进制的用户。__CAPGO_KEEP_0__的 兼容性检查

Troubleshooting

CI 中未应用补丁。 确保 patches/ 已提交并未被忽略。对于 patch-package,请检查 CI 是否使用 --ignore-scripts,它会跳过 postinstallBun,检查 patchedDependencies 已提交的 package.json.

我的本地变更无效。 您编辑了文件但未重新构建。请运行 bunx cap sync,然后在 Xcode 中清理: Product > Clean Build Folder,在 Android 上 ./gradlew clean. 使用 SPM 也需要重置包缓存。

bun patch --commit 提示没有任何变化。 您编辑的文件不是该包的一部分(例如在另一个文件夹中拷贝的文件)。请编辑第 1 步打印的路径 Bun。

升级插件后,补丁失败。 检查修复是否已包含在新版本中。如果没有,请重新对新版本进行补丁。

插件编译成功,但在该功能上应用程序崩溃。 补丁跳过了插件自己的测试套件。请在真实设备上测试修补路径,包括两种平台。 Capacitor iOS 故障排除指南 和 Android 故障排除指南 涵盖如何阅读本机日志。

Live updates for Capacitor apps

实时更新 Capgo 应用程序

最新博客

Capgo 为您提供创建真正专业的移动应用所需的最佳见解。