Um einen Capacitor-Plugin zu patchen, bearbeiten Sie die Dateien des Plugins in node_modulesSpeichern Sie die Änderung als Differenz mit bun patch --commit oder patch-package auf npm und Yarn, pnpm patch-commit auf pnpm), committiere das generierte Datei in patches/Dann führe aus bunx cap sync so dass die native Projekte es aufnehmen. Der Paketmanager wiederholt die Patches bei jeder Installation, für dein Team und in CI.
Patching ist die richtige Wahl, wenn ein Plugin einen kleinen Fehler hat, eine Versionsbeschränkung, die deinen Build blockiert, oder ein upstream-Fix, der eingereicht wurde, aber noch nicht veröffentlicht wurde. Diese Anleitung deckt den Workflow für jeden Paketmanager ab, wie native Patches auf Xcode und Gradle zugreifen und wann ein Fork oder ein upstream-PR die bessere Wahl ist.
Warum funktioniert Patching für native Plugin code
Ein Capacitor-Plugin ist ein npm-Paket mit drei Teilen: JavaScript in dist/Android code in android/, und iOS code in ios/ plus eine podspec und/oder Package.swiftCapacitor kompiliert die native Teile direkt aus node_modules:
- Android:
android/capacitor.settings.gradleeinschließt jedes Plugins-VerzeichnisandroidOrdner vonnode_modules. - iOS mit CocoaPods: Die Podfile verweist auf jedes Plugin
:path => '../../node_modules/...'. - iOS mit SPM:
CapApp-SPM/Package.swiftverweist auf jedes Plugin durch lokale Pfad innode_modules.
So eine Änderung an node_modules/@scope/plugin/ios/Sources/... endet in Ihrem App-Binary nach cap sync und einem Neubau. Es muss nichts veröffentlicht werden.
Bevor Sie ein Patch anwenden
- Überprüfen Sie eine Veröffentlichung. Betrachte die Änderungsprotokolle des Plugins und öffne die PRs. Eine Aktualisierung ist besser als ein Patch.
- Lese die Lizenz. MIT und Apache-2.0 erlauben private Modifikationen. Copyleft-Lizenzen wie GPL oder MPL-2.0 können Sie dazu verpflichten, die modifizierte Quelle zu veröffentlichen, wenn Sie die App verteilen. Überprüfen Sie dies, bevor Sie die App verschicken.
- Erkläre, warum. Füge die URL des Issues oder eine Zeilenbegründung in deinem Commit-Bereich ein. Sechs Monate später erinnert sich niemand mehr daran, warum.
patches/hat ein Datei in sich.
Patching 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 eine Differenz und speichert sie in package.json:
{
"patchedDependencies": {
"@capacitor/haptics@8.0.2": "patches/@capacitor%2Fhaptics@8.0.2.patch"
}
}
Commit beide package.json und das patches/ Ordner. Jeder bun install, einschließlich bun install --frozen-lockfile in CI, wird die Patches angewendet.
Der Schlüssel enthält die genaue Version. Wenn Sie die Plugin-Version erhöhen, Bun passt sich nicht mehr an die Patches an, also erstellen Sie es neu für die neue Version oder löschen Sie es, wenn der Fix abgeschickt wurde.
Patching mit npm oder Yarn: patch-package
npm install --save-dev patch-package
Fügen Sie ein postinstall Skript, sodass 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 fehlt bei der Installation mit einer klaren Meldung.
Yarn Berry hat seinen eigenen yarn patch <pkg> / yarn patch-commit -s <path> Fluss, der die Patches im resolutions field.
Patching mit pnpm
pnpm patch @capacitor/haptics
# edit the temporary folder pnpm prints
pnpm patch-commit <path-printed-above>
pnpm speichert die Patches unter patchedDependencies und appliziert sie bei der Installation.
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.txtAGP 9 lehnt dies ab. Sie können nicht auf eine Veröffentlichung warten.
bun patch some-capacitor-plugin
Bearbeiten 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 Plugin-Build-Fehler mit AGP 9.
Beispiel: Lockere eine iOS-Abhängigkeitsbeschränkung
Zwei Plugins greifen auf unterschiedliche Versionen des gleichen SDK zu und CocoaPods kann sie nicht lösen. Wenn Sie die Funktionsfähigkeit des Plugins mit der neueren SDK bestätigt haben, lockere Sie seine podspec:
- s.dependency 'FirebaseMessaging', '11.15.0'
+ s.dependency 'FirebaseMessaging', '>= 11.15.0', '< 13.0'
Für SPM-Anwendungen lebt die gleiche Beschränkung im Plugin-Code 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 noch die alte Version enthält. Mit SPM verwenden Sie Datei > Packages > Lösung von Paketversionen in Xcode.
Patching Capacitor Kern selbst
Manchmal liegt der Fehler in @capacitor/android, @capacitor/ios oder im CLI, und die Lösung befindet sich in einem upstream-Pull-Request. Sie können diese Pakete auf die gleiche Weise patchen, aber jede Mannschaft endet schließlich damit, die gleichen Diffs zu pflegen.
Capgo publiziert @capgo/capacitor-patch zur Unterstützung dieser Funktion. Es ist ein Hook-Paket mit einem Katalog kleiner, versionsgesteuerter 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;
Pakete patchen, bevor cap sync und cap updateund native Projekt-Patches laufen danach. bunx capgo-capacitor-patch doctor , und native Projekt-Patches laufen nach. strict: true, die Synchronisierung fehlt, wenn ein ausgewählter Patch nicht mehr anwendbar ist, was Ihnen sagt, dass eine Aktualisierung ihn veraltet hat. plugin docs für die vollständige Optionenliste.
zur vollständigen Liste der Optionen.
| Situation | Beste Option |
|---|---|
| Ein paar Zeilen, bereits in der Quellcode-Übersicht | Patch, nach dem nächsten Release entfernen |
| Versionseinschränkung zu streng | Patch, ein Issue in der Quellcode-Übersicht erstellen |
| Fehler ohne noch keine Lösung in der Quellcode-Übersicht | Patch und ein Pull-Request mit dem gleichen Diff senden |
| Neue Funktion oder große Refaktorisierung | Fork, unter Ihrem eigenen Namespace veröffentlichen |
| Plugin wurde aufgegeben | Fork oder auf ein gepflegtes Plugin umschalten |
Forken Sie 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 Ein Skript, und nicht jeder Paketmanager läuft Abhängigkeitslebenszyklus-Skripte standardmäßig. Ein veröffentlichtes Paket vermeidet das.
Denken Sie daran, dass der npm Name den Modulnamen ändert, den CLI für SPM generiert ("@acme/capacitor-foo becomes AcmeCapacitorFoo), so aktualisieren Sie das Fork Package.swift zum Abgleichen. Details finden Sie in migrieren Sie ein Capacitor-Plugin zu SPM.
Bevor Sie ein Plugin für eine fehlende Funktion forkieren, überprüfen Sie die Capgo Plugin-Verzeichnis. Es könnte bereits ein gepflegter Plugin geben, das es abdeckt.
Upstreaming
Ziel ist es, Ihren Patch 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. Hüter integrieren kleine, getestete Fixes viel schneller als Issue-Berichte allein.
Patches und Live-Updates
Ihr Web-Bundle enthält das Plugin’s JavaScript von dist/, also schippert ein Patch für die JS-Seite mit der nächsten Web-Build. Mit Capgo Live-Updates dieses erreicht Benutzer ohne einen Store-Release.
Native-Patches sind anders. Änderungen an Swift, Kotlin, Java, Gradle, podspec oder Package.swift werden nur in einer neuen native Build wirksam, die den Stores zugeführt wird. Drücken Sie nicht eine Web-Bundle aus, die auf einem native Patch angewiesen ist, an Benutzer, die noch die alte Binärdatei ausführen. Capgo’s Kompatibilitätsprüfung vergleicht native Plugin-Versionen zwischen einem Bundle und einem Channel, um dies zu erkennen.
Fehlerbehebung
Die Patches werden nicht in CI angewendet. Make sure patches/ eingereicht und nicht ignoriert ist. Für patch-package, überprüfen Sie, ob CI --ignore-scripts, die überspringt postinstallüberspringt. Für Bun, überprüfen Sie, ob patchedDependencies im eingereichten 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 löschen, auf Android ./gradlew clean. Mit SPM werden auch die Paket-Caches zurückgesetzt.
bun patch --commit er gibt an, dass es keine Änderungen gibt. Sie haben einen Datei bearbeitet, die nicht zum Paket gehört (z. B. eine aufgehobene Kopie in einem anderen Ordner). Bearbeiten Sie den Pfad Bun aus Schritt 1.
Die Patches scheitern nach dem Plugin-Update. Überprüfen Sie, ob die Reparatur 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-Suite des Plugins. Testen Sie den gepatchten Pfad auf einem echten Gerät auf beiden Plattformen. Der Capacitor iOS-Fehlersuche-Leitfaden und der Android-Fehlersuche-Leitfaden erklären, wie man native Logs liest.