Um ein Capacitor-Plugin zu patchen, bearbeiten Sie die Dateien des Plugins node_modules, speichern Sie die Änderung als Diff mit bun patch --commit (oder patch-package auf npm und Yarn, pnpm patch-commit auf pnpm), committen Sie das generierte File in patches/, führen Sie dann bunx cap sync Damit nehmen die native Projekte es auf. Der Paketmanager wiederholt die Patches bei jeder Installation, für Ihre Team und in CI.
Patching ist die richtige Entscheidung, wenn ein Plugin einen kleinen Fehler hat, eine Versionsbeschränkung, die Ihren Build blockiert, oder eine aufwärts gerichtete Fixierung, die eingereicht wurde, aber noch nicht veröffentlicht wurde. Diese Anleitung deckt das Workflow für jeden Paket-Manager ab, wie native Patches auf Xcode und Gradle gelangen und wann ein Fork oder ein aufwärts gerichteter PR die bessere Wahl ist.
Warum funktioniert das Patchen für native Plugins code
Ein Capacitor-Plugin ist ein npm-Paket mit drei Teilen: JavaScript in dist/, Android code in android/, und iOS code in ios/ zusammen mit einer podspec und/oder Package.swift.Capacitor kompiliert die nativen Teile direkt von node_modules:
- Android:
android/capacitor.settings.gradlebeinhaltet jedes PluginsandroidFachordner vonnode_modules. - iOS mit CocoaPods: Die Podfile verweist auf jedes Plugin mit
:path => '../../node_modules/...'. - iOS mit SPM:
CapApp-SPM/Package.swiftverweist auf jeden Plugin über lokalen Pfad innode_modules.
Also ändert sich ein Plugin node_modules/@scope/plugin/ios/Sources/... endet in deinem App-Binary nach cap sync und einem Neubuild. Es muss nichts veröffentlicht werden.
Bevor Sie ein Plugin patchen
- Überprüfen Sie, ob ein Release verfügbar ist. Betrachte die Änderungsliste des Plugins und öffne die PRs. Eine Aktualisierung ist besser als ein Patch.
- Lesen Sie die Lizenz. MIT und Apache-2.0 erlauben private Änderungen. Copyleft-Lizenzen wie GPL oder MPL-2.0 können Sie dazu verpflichten, veränderte Quellcode zu veröffentlichen, wenn Sie die App verteilen. Überprüfen Sie dies, bevor Sie die App freigeben.
- Schreiben Sie, warum. Fügen Sie die URL des Issues oder eine Zeilenbegründung in Ihrem Commit-Botschaft ein. Sechs Monate später weiß niemand mehr, warum.
patches/hat ein Datei in sich.
Patchen mit Bun
Bun hat Patching in sich. Kein extra Paket, kein postinstall Skript.
# 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
Schritt 1 gibt Bun Ihnen eine private Kopie des Pakets in node_modules, damit Änderungen den globalen Cache von Bun nicht berühren. Schritt 3 erstellt einen Diff und speichert ihn in package.json:
{
"patchedDependencies": {
"@capacitor/haptics@8.0.2": "patches/@capacitor%2Fhaptics@8.0.2.patch"
}
}
Commit beide package.json Beide patches/ Ordner. Jeder bun installVerzeichnis. Jeder bun install --frozen-lockfile wird in CI angewendet.
The key contains the exact version. If you bump the plugin, Bun no longer matches the patch, so recreate it for the new version or delete it if the fix shipped.
Patchen mit npm oder Yarn: patch-package
npm install --save-dev patch-package
Fügen Sie ein postinstall Skript, damit Patches nach jedem Installieren angewendet werden.
{
"scripts": {
"postinstall": "patch-package"
}
}
Dann bearbeiten Sie die Dateien in node_modules und generieren Sie den Patch:
npx patch-package @capacitor/haptics
Dies schreibt patches/@capacitor+haptics+8.0.2.patchin. Commit es. Wenn der Patch nach einem Upgrade nicht mehr angewendet wird, patch-package versagt die Installation mit einer klaren Meldung.
Yarn Berry hat seinen eigenen yarn patch <pkg> / yarn patch-commit -s <path> Ablauf, der den Patch im resolutions field.
Patching mit pnpm
pnpm patch @capacitor/haptics
# edit the temporary folder pnpm prints
pnpm patch-commit <path-printed-above>
pnpm registriert die Patches unter patchedDependencies und wendet sie bei der Installation an.
Beispiel: Behebung eines Fehler im nativen Build eines Plugins
Ein häufiges Szenario: Ihre App verwendet AGP 9, und ein älteres Plugin android/build.gradle verweist noch immer auf proguard-android.txt, die AGP 9 ablehnt. Sie können nicht auf eine Veröffentlichung warten.
bun patch some-capacitor-plugin
Editieren 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'
}
}
Speichern und synchronisieren:
bun patch --commit node_modules/some-capacitor-plugin
bunx cap sync android
cd android && ./gradlew assembleDebug
The full background on this error is in fixen Sie Capacitor-Fehler im Plugin-Builder mit AGP 9.
Beispiel: Lockern Sie eine iOS-Abhängigkeit
Zwei Plugins setzen unterschiedliche Versionen des gleichen SDK fest und CocoaPods kann sie nicht lösen. Wenn Sie die Funktionsfähigkeit des Plugins mit der neueren SDK bestätigt haben, lockern Sie die podspec:
- s.dependency 'FirebaseMessaging', '11.15.0'
+ s.dependency 'FirebaseMessaging', '>= 11.15.0', '< 13.0'
Für SPM-Anwendungen lebt dieselbe Einschränkung im Plugin’s 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")
Dann:
bunx cap sync ios
Mit CocoaPods benötigen Sie möglicherweise cd ios/App && pod update FirebaseMessaging einmal, weil Podfile.lock immer noch die alte Version. Mit SPM verwenden Sie Datei > Packages > Packageversionen auflösen in Xcode.
Patching Capacitor Kern selbst
Manchmal liegt der Fehler in @capacitor/android, @capacitor/ios oder im CLI, und die Reparatur befindet sich in einem upstream-Pull-Request. Sie können diese Pakete auf die gleiche Weise patchen, aber jede Mannschaft endet mit der gleichen Diffs.
Capgo veröffentlicht @capgo/capacitor-patch für dies. Es ist ein hook-only-Paket mit einem Katalog kleiner, version-gesteuerter Patches, die auf ihre upstream-PRs verweisen. Es tut nichts, bis Sie sich entscheiden:
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;
Paket-Patches laufen vorher cap sync und cap update, und native Projekt-Patches laufen nachher. bunx capgo-capacitor-patch doctor führt ein Trockentest durch. Mit strict: true, wird ein Synchronisierungsversuch fehlschlagen, wenn ein ausgewählter Patch nicht mehr anwendbar ist, was Ihnen sagt, wenn ein Upgrade ihn veraltet hat. Siehe die plugin docs für die vollständige Liste der Optionen.
Patch, fork oder upstream?
| Situation | Beste Option |
|---|---|
| Ein paar Zeilen, bereits in der upstream-Merge | Patch, nach dem nächsten Release entfernen |
| Versionseinschränkung zu streng | Patch, ein Issue upstream öffnen |
| Bug ohne noch keine Fix von upstream | Patch und ein PR mit demselben Diff senden |
| Neue Funktion oder große Refaktorisierung | Fork, unter Ihrem Scope veröffentlichen |
| Plugin aufgegeben | Fork, oder auf ein gepflegtes Plugin umsteigen |
Forking gut
If you fork, publish it so installs stay reproducible:
# in the fork, rename to your scope in package.json: "@acme/capacitor-foo"
bun run build
bun publish --access restricted
Aus einer Git-URL installieren funktioniert auch, aber die Plugin- dist/ Ordner muss in diesem Branch existieren oder durch einen prepare Skript und nicht jeder Paketmanager läuft die Abhängigkeitslebenszyklus-Skripte standardmäßig aus. Ein veröffentlichtes Paket vermeidet das.
Denken Sie daran, dass der npm-Name den Modulnamen des von CLI für SPM generierten Moduls ändert (@acme/capacitor-foo wird AcmeCapacitorFoo), also aktualisieren Sie die Forks Package.swift zum Anpassen. Details finden Sie in migrieren Sie ein Capacitor-Plugin auf SPM.
Bevor Sie ein Plugin für eine fehlende Funktion forken, überprüfen Sie das Capgo-Plugin-Verzeichnis. Es könnte bereits ein gepflegtes Plugin geben, das es abdeckt.
Upstreaming
Das Ziel ist, Ihre Patches zu löschen. Öffnen Sie ein Issue mit einer minimalen Reproduktion, Ihren Capacitor- und Plugin-Versionen und dem Patch-Diff. Dann öffnen Sie einen PR. Wartungsbeauftragte integrieren kleine, getestete Fixes viel schneller als Issue-Berichte allein.
Patches und Live-Updates
Ihr Web-Bundle enthält die JavaScript-Dateien des Plugins dist/daher wird ein Patch auf der JS-Seite mit der nächsten Web-Ausgabe verschickt. Mit Capgo Live-Updates wird das Update den Benutzern ohne eine Store-Ausgabe erreicht.
Nativ-Patches sind anders. Änderungen an Swift, Kotlin, Java, Gradle, podspec oder Package.swift wirken nur in einer neuen nativen Ausgabe, die an die Stores geschickt wird. Drücken Sie nicht ein Web-Bundle aus, das auf einem nativen Patch angewiesen ist, an Benutzer weiter, die noch die alte Binärdatei ausführen. Capgo Kompatibilitätsprüfung vergleicht die nativen Plugin-Versionen zwischen einem Bundle und einem Kanal, um dies zu erkennen.
Fehlerbehebung
Das Update wird nicht in CI angewendet. Make sure patches/ wird eingereicht und nicht ignoriert. Für patch-package, überprüfen Sie, dass CI nicht verwendet --ignore-scripts, das überspringt postinstall. Überprüfen Sie für Bun patchedDependencies ist im committierten package.json.
Meine native Änderung hat keinen Effekt. Sie haben das Datei geändert, aber nicht neu gebaut. Führen Sie bunx cap sync, dann clean: in Xcode Produkt > Ordner für Clean Build löschen, auf Android ./gradlew clean. Mit SPM resetzt man auch die Paket-Caches.
bun patch --commit sagt, es gäbe keine Änderungen. Sie haben eine Datei geändert, die nicht zum Paket gehört (z.B. eine gehobene Kopie in einem anderen Ordner). Bearbeiten Sie den Pfad Bun aus Schritt 1.
Die Patches scheitern nach dem Plugin-Upgrade. Überprüfen Sie, ob der Fix in der neuen Version enthalten ist. Wenn nicht, wiederholen Sie den Patch gegen die neue Version.
Das Plugin baut, aber die App stürzt auf dieser Funktion ab. Patches überspringen die eigenen Test des Plugins. Testen Sie den gepatchten Pfad auf einem realen Gerät auf beiden Plattformen. Der Capacitor iOS-Fehlersuche-Leitfaden und Android-Fehlersuche-Anleitung erklären, wie man native Logs liest.