Untuk melakukan patch pada plugin Capacitor, edit file plugin di node_modules, simpan perubahan sebagai diff dengan bun patch --commit (atau patch-package di npm dan Yarn, pnpm patch-commit di pnpm), commit file yang dihasilkan ke patches/, lalu jalankan bunx cap sync agar proyek native bisa mendeteksinya. Package manager menerapkan ulang patch di setiap install, untuk tim Anda dan di CI.
Patching adalah solusi tepat saat plugin punya bug kecil, batasan versi yang menghambat build, atau perbaikan upstream yang sudah di-merge tapi belum dirilis. Panduan ini membahas workflow untuk tiap package manager, cara patch native sampai ke Xcode dan Gradle, dan kapan fork atau upstream PR lebih tepat.
Mengapa patching berhasil untuk plugin native code
Plugin Capacitor adalah package npm dengan tiga bagian: JavaScript di dist/, Android code di android/, dan iOS code di ios/ ditambah podspec dan/atau Package.swift. Capacitor mengompilasi bagian native langsung dari node_modules:
- Android:
android/capacitor.settings.gradlemencakup setiap pluginandroidfolder darinode_modules. - iOS dengan CocoaPods: Podfile merujuk setiap plugin dengan
:path => '../../node_modules/...'. - iOS dengan SPM:
CapApp-SPM/Package.swiftmerujuk setiap plugin via path lokal dinode_modules.
Jadi, sebuah perubahan pada node_modules/@scope/plugin/ios/Sources/... akhirnya masuk ke binary app Anda setelah cap sync dan rebuild. Tidak ada yang perlu dipublikasikan.
Sebelum Anda melakukan patch
- Cek apakah ada rilis baru. Cek changelog dan PR terbuka plugin tersebut. Upgrade lebih baik daripada patching.
- Baca lisensinya. Lisensi MIT dan Apache-2.0 mengizinkan modifikasi privat. Lisensi copyleft seperti GPL atau MPL-2.0 dapat mewajibkan Anda mempublikasikan source code yang dimodifikasi saat mendistribusikan aplikasi. Cek dulu sebelum rilis.
- Catat alasannya. Sertakan URL issue atau alasan singkat dalam commit message Anda. Enam bulan kemudian, tidak ada yang ingat alasannya.
patches/berisi file.
Patching dengan Bun
Bun sudah memiliki fitur patching bawaan. Tanpa paket tambahan, tanpa 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
Langkah 1 membuat Bun memberi Anda salinan privat paket di node_modules, sehingga editan tidak menyentuh cache global Bun. Langkah 3 menulis diff dan mencatatnya di package.json:
{
"patchedDependencies": {
"@capacitor/haptics@8.0.2": "patches/@capacitor%2Fhaptics@8.0.2.patch"
}
}
Commit keduanya package.json dan patches/ folder. Setiap bun install, termasuk bun install --frozen-lockfile di CI, menerapkan patch tersebut.
Key tersebut berisi versi yang tepat. Jika Anda menaikkan versi plugin, Bun tidak akan cocok lagi dengan patch, jadi buat ulang untuk versi baru atau hapus jika perbaikannya sudah dirilis.
Patching dengan npm atau Yarn: patch-package
npm install --save-dev patch-package
Tambahkan postinstall script agar patch diterapkan setiap kali install:
{
"scripts": {
"postinstall": "patch-package"
}
}
Kemudian edit file di node_modules dan buat patch-nya:
npx patch-package @capacitor/haptics
Ini akan menulis patches/@capacitor+haptics+8.0.2.patch. Commit perubahan tersebut. Jika patch gagal diterapkan setelah upgrade, patch-package proses install akan gagal dengan pesan yang jelas.
Yarn Berry memiliki yarn patch <pkg> / yarn patch-commit -s <path> flow sendiri yang menyimpan patch di field resolutions .
Patching dengan pnpm
pnpm patch @capacitor/haptics
# edit the temporary folder pnpm prints
pnpm patch-commit <path-printed-above>
pnpm mencatat patch di bawah patchedDependencies dan menerapkannya saat install.
Contoh: memperbaiki error Native Build pada plugin
Kasus umum: aplikasi Anda menggunakan AGP 9, sedangkan plugin lama android/build.gradle masih mereferensikan proguard-android.txt, yang ditolak oleh AGP 9. Anda tidak bisa menunggu rilis baru.
bun patch some-capacitor-plugin
Edit 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'
}
}
Simpan dan sinkronisasi:
bun patch --commit node_modules/some-capacitor-plugin
bunx cap sync android
cd android && ./gradlew assembleDebug
Penjelasan lengkap mengenai error ini ada di cara memperbaiki error build plugin Capacitor dengan AGP 9.
Contoh: melonggarkan batasan dependency iOS
Dua plugin mengunci versi SDK yang berbeda dan CocoaPods tidak bisa menyelesaikannya. Jika Anda sudah memastikan plugin berfungsi dengan SDK yang lebih baru, longgarkan podspec-nya:
- s.dependency 'FirebaseMessaging', '11.15.0'
+ s.dependency 'FirebaseMessaging', '>= 11.15.0', '< 13.0'
Untuk aplikasi SPM, batasan yang sama ada di 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")
Lalu:
bunx cap sync ios
Dengan CocoaPods, Anda mungkin perlu cd ios/App && pod update FirebaseMessaging sekali, karena Podfile.lock masih menyimpan versi lama. Dengan SPM, gunakan File > Packages > Resolve Package Versions di Xcode.
Mem-patch core Capacitor itu sendiri
Terkadang bug ada di @capacitor/android, @capacitor/ios atau CLI, dan perbaikannya ada di upstream pull request. Anda bisa mem-patch package tersebut dengan cara yang sama, tapi setiap tim akhirnya mengelola diff yang sama.
Capgo merilis @capgo/capacitor-patch untuk ini. Ini package hook-only dengan katalog patch kecil yang dibatasi versi dan tertaut kembali ke PR upstream masing-masing. Package ini tidak melakukan apa pun sampai Anda mengaktifkannya:
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;
Patch paket dijalankan sebelum cap sync dan cap update, dan patch proyek native dijalankan setelahnya. bunx capgo-capacitor-patch doctor melakukan dry run. Dengan strict: true, sync gagal saat patch yang dipilih tidak lagi bisa diterapkan, yang memberi tahu Anda kapan upgrade membuatnya usang. Lihat dokumentasi plugin untuk daftar opsi lengkapnya.
Patch, fork, atau upstream?
| Situasi | Opsi terbaik |
|---|---|
| Beberapa baris, perbaikan sudah di-merge upstream | Patch, hapus setelah rilis berikutnya |
| Batasan versi terlalu ketat | Patch, buka issue di upstream |
| Bug yang belum ada perbaikan upstream | Patch dan kirim PR dengan diff yang sama |
| Fitur baru atau refactor besar | Fork, lalu publish di scope Anda |
| Plugin sudah tidak dikelola | Fork, atau pindah ke plugin yang aktif |
Cara melakukan forking yang benar
Jika Anda melakukan fork, publish agar instalasi tetap reproducible:
# in the fork, rename to your scope in package.json: "@acme/capacitor-foo"
bun run build
bun publish --access restricted
Instalasi via git URL juga bisa, tapi folder dist/ plugin harus ada di branch tersebut atau di-build via prepare script, dan tidak semua package manager menjalankan lifecycle script secara default. Package yang sudah di-publish menghindari masalah ini.
Ingat bahwa nama npm mengubah nama native module yang dihasilkan CLI untuk SPM (@acme/capacitor-foo menjadi AcmeCapacitorFoo), jadi perbarui fork-nya Package.swift agar sesuai. Detailnya ada di migrasi plugin Capacitor ke SPM.
Sebelum Anda melakukan fork pada plugin untuk fitur yang hilang, cek direktori plugin Capgo. Mungkin sudah ada plugin yang dikelola yang mencakup fitur tersebut.
Upstreaming
Tujuannya adalah untuk menghapus patch Anda. Buka issue dengan repro minimal, versi Capacitor dan plugin Anda, serta patch diff. Kemudian buka PR. Maintainer akan melakukan merge pada perbaikan kecil yang sudah dites jauh lebih cepat daripada sekadar laporan issue.
Patch dan live updates
Web bundle Anda menyertakan JavaScript plugin dari dist/, jadi patch pada sisi JS akan ikut terkirim dengan web build berikutnya. Dengan Live updates Capgo yang menjangkau pengguna tanpa rilis store.
Patch native itu berbeda. Perubahan pada Swift, Kotlin, Java, Gradle, podspec atau Package.swift hanya akan berpengaruh pada Native Build baru yang dikirim ke store. Jangan push web bundle yang bergantung pada native patch ke pengguna yang masih menjalankan binary lama. Capgo memiliki pemeriksaan kompatibilitas yang membandingkan versi plugin native antara bundle dan channel untuk mendeteksi hal ini.
Pemecahan Masalah
Patch tersebut tidak diterapkan di CI. Pastikan patches/ di-commit dan tidak diabaikan. Untuk patch-package, pastikan CI tidak menggunakan --ignore-scripts, yang melewati postinstall. Untuk Bun, pastikan patchedDependencies sudah masuk dalam commit package.json.
Perubahan native saya tidak ada efeknya. Anda sudah mengedit file tapi belum rebuild. Jalankan bunx cap sync, lalu clean: di Xcode Produk > Bersihkan Folder Build, di Android ./gradlew clean. Dengan SPM, reset juga package cache-nya.
bun patch --commit mengatakan tidak ada perubahan. Anda mengedit file yang bukan bagian dari package (misalnya salinan hoisted di folder lain). Edit path Bun yang muncul di langkah 1.
Patch gagal setelah upgrade plugin. Cek apakah perbaikannya sudah ada di rilis baru. Jika belum, buat ulang patch pada versi terbaru.
Plugin berhasil di-build, tapi app crash saat fitur tersebut digunakan. Patch melewati test suite bawaan plugin. Tes jalur patch pada perangkat asli di kedua platform. Artikel ini Panduan troubleshooting Capacitor iOS dan Panduan troubleshooting Android mencakup cara membaca native logs.