Langsung ke konten utama

Cara Menggunakan SPM Package Traits di Capacitor 8

Gunakan SPM package traits di Capacitor 8: aktifkan fitur plugin opsional dengan packageTraits, atur swiftToolsVersion 6.1, dan tambahkan traits ke plugin Anda sendiri.

Ilustrasi konfigurasi Swift Package Manager di proyek iOS Capacitor

Untuk menggunakan SPM package traits di Capacitor 8, atur experimental.ios.spm.swiftToolsVersion ke "6.1" dan daftar trait per plugin di bawah experimental.ios.spm.packageTraits di konfigurasi Capacitor Anda, lalu jalankan bunx cap sync ios. CLI menulis trait tersebut ke dalam CapApp-SPM/Package.swiftyang dihasilkan, dan SwiftPM mem-build plugin dengan dependensi opsional dan path code yang sesuai. Ini memerlukan Capacitor CLI 8.3.0 atau versi terbaru dan hanya berlaku untuk proyek iOS yang menggunakan Swift Package Manager.

Trait menutup celah fitur besar terakhir antara SPM dan CocoaPods untuk plugin: dependensi native opsional yang dulunya merupakan podspec subspecs. Panduan ini membahas sisi aplikasi, sisi pembuat plugin, dan batasan dukungan eksperimental saat ini.

Apa itu package traits

Package traits berasal dari proposal Swift Evolution SE-0450, yang diimplementasikan di Swift 6.1 (Xcode 16.3 ke atas). Sebuah package mendeklarasikan trait bernama di dalam Package.swift. Pengguna memilih mana yang ingin diaktifkan saat mereka bergantung pada package tersebut. Sebuah trait dapat:

  • membuat dependensi menjadi opsional ("condition: .when(traits: [...]) pada dependensi target),
  • aktifkan path code, karena setiap trait yang diaktifkan tersedia sebagai kondisi kompilasi (#if TraitName),
  • ubah pengaturan build seperti defines atau linker flags,
  • aktifkan trait lainnya.

Package juga bisa menandai trait sebagai default. Trait ini akan aktif kecuali consumer memberikan daftar eksplisit.

Jika Anda familiar dengan subspecs CocoaPods atau fitur Cargo di Rust, konsepnya sama.

Mengapa ini penting di Capacitor

Capacitor menghasilkan Package.swift untuk Anda, jadi Anda tidak bisa mengedit baris dependensi secara manual untuk menyertakan trait. Sebelum CLI 8.3, pembuat plugin dengan SDK native opsional punya dua pilihan buruk di SPM: selalu melakukan link ke SDK, yang memperbesar ukuran dan terkadang menambah beban kepatuhan privasi atau ekspor, atau merilis plugin kedua. Kasus umum:

  • SQLite terenkripsi vs plain (SQLCipher),
  • SDK analytics dengan atau tanpa pengumpulan identifier iklan,
  • SDK vendor opsional untuk satu penyedia pembayaran atau login,
  • tooling khusus untuk debug.

Aktifkan trait di aplikasi Anda

1. Cek versi

bunx cap --version      # 8.3.0 or later
xcodebuild -version     # Xcode 26 (required by Capacitor 8 anyway)

Proyek harus menggunakan SPM: ios/App/CapApp-SPM ada. Jika Anda menggunakan CocoaPods, lihat cara migrasi aplikasi Capacitor ke SPM.

2. Cari nama trait plugin

Open the plugin’s Package.swift di node_modules dan cari bagian traits: array, atau cek README-nya. Nama trait bersifat case-sensitive.

3. Konfigurasi Capacitor

import type { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.example.app',
  appName: 'Example',
  webDir: 'dist',
  experimental: {
    ios: {
      spm: {
        swiftToolsVersion: '6.1',
        packageTraits: {
          '@acme/capacitor-db': ['.defaults', 'SQLCipher'],
        },
      },
    },
  },
};

export default config;

Kuncinya adalah nama package npm dari plugin tersebut. Nilainya adalah daftar trait yang ingin diaktifkan.

4. Sync dan cek outputnya

bunx cap sync ios

Yang dihasilkan ios/App/CapApp-SPM/Package.swift sekarang dimulai dengan // swift-tools-version: 6.1 dan baris dependensi plugin memuat trait:

.package(name: "AcmeCapacitorDb", path: "../../../node_modules/@acme/capacitor-db", traits: [.defaults, "SQLCipher"])

CLI menulis .defaults (atau defaults, .default, default dalam kondisi apa pun) sebagai SwiftPM .defaults nilai, dan nama lainnya sebagai string dalam tanda kutip.

Build di Xcode. Jika Xcode masih menampilkan graph lama, gunakan File > Packages > Reset Package Caches.

Aturan yang ditegakkan oleh CLI

Capacitor CLI memvalidasi config saat sync:

  • Jika ada plugin dengan daftar trait yang tidak kosong dan swiftToolsVersion tidak ditemukan, sync akan berhenti dengan pesan “Package traits require an explicit Swift tools version of 6.1 or higher.”
  • Jika swiftToolsVersion lebih rendah dari 6.1, sync akan berhenti dan memberi tahu bahwa versinya terlalu rendah.
  • swiftToolsVersion harus terlihat seperti 6.1 atau 6.1.0.
  • Plugin dengan array kosong akan dianggap tidak terdaftar.

Simpan atau hapus default traits

Mendaftarkan trait akan menggantikan default. Bandingkan:

Nilai konfigurasi Hasil
tidak terdaftar trait default plugin
['SQLCipher'] saja SQLCipher, default nonaktif
['.defaults', 'SQLCipher'] default plus SQLCipher

Baca dokumentasi plugin sebelum menghapus default. Plugin mungkin menempatkan backend standarnya di balik sebuah default trait.

Tambahkan trait ke plugin Anda sendiri

Jika Anda mengelola plugin dengan SDK opsional, berikut adalah panduan lengkap Package.swift. Nama package harus sesuai dengan nama yang CLI Capacitor dari nama npm Anda ("@acme/capacitor-db menjadi AcmeCapacitorDb). Lihat migrasi plugin Capacitor ke SPM untuk aturannya.

// swift-tools-version: 6.1
import PackageDescription

let package = Package(
    name: "AcmeCapacitorDb",
    platforms: [.iOS(.v15)],
    products: [
        .library(name: "AcmeCapacitorDb", targets: ["DbPlugin"])
    ],
    traits: [
        .trait(name: "SQLCipher", description: "Link SQLCipher and enable encrypted databases."),
        .default(enabledTraits: [])
    ],
    dependencies: [
        .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"),
        .package(url: "https://github.com/sqlcipher/SQLCipher.swift.git", from: "4.10.0")
    ],
    targets: [
        .target(
            name: "DbPlugin",
            dependencies: [
                .product(name: "Capacitor", package: "capacitor-swift-pm"),
                .product(name: "Cordova", package: "capacitor-swift-pm"),
                .product(
                    name: "SQLCipher",
                    package: "SQLCipher.swift",
                    condition: .when(traits: ["SQLCipher"])
                )
            ],
            path: "ios/Sources/DbPlugin"
        )
    ],
    swiftLanguageModes: [.v5]
)

Cek repositori SDK sendiri untuk URL package, nama produk, dan versi terbarunya sebelum menyalin ini.

Hal-hal yang sering terlewatkan:

  • Perubahan tools version 6.x mengubah mode bahasa default ke Swift 6 untuk target Anda. Capacitor belum mendukung Swift 6 secara resmi, jadi tetaplah gunakan swiftLanguageModes: [.v5] kecuali code Anda sudah siap untuk strict concurrency.
  • Menaikkan tools version plugin ke 6.1 berarti pengguna butuh Xcode 16.3+. Capacitor 8 apps sudah mewajibkan Xcode 26, jadi ini bukan kendala baru.

Gunakan trait di code

Trait yang aktif adalah kondisi kompilasi pada target package Anda:

#if SQLCipher
import SQLCipher
#endif

@objc func open(_ call: CAPPluginCall) {
    let key = call.getString("encryptionKey")
    #if SQLCipher
    // open with key
    #else
    if key != nil {
        call.unavailable("Encryption requires the SQLCipher trait. Enable it in experimental.ios.spm.packageTraits.")
        return
    }
    #endif
    // open without encryption
}

Kembalikan error yang jelas menyebutkan nama trait saat fitur mati. Jika tidak, developer app akan melihat kegagalan tanpa pesan (silent failure) dan menyalahkan plugin.

Anda juga bisa mendefinisikan flag sendiri dengan swiftSettings: [.define("ACME_SQLCIPHER", .when(traits: ["SQLCipher"]))] jika Anda lebih suka menggunakan nama dengan prefix.

Desain trait agar bersifat aditif

SwiftPM menyatukan trait di seluruh dependency graph. Jika dua package bergantung pada plugin Anda dengan trait berbeda, maka union-nya akan diaktifkan. Jadi:

  • Mengaktifkan sebuah trait harus menambah kapabilitas, bukan menghapus API atau mengubah default.
  • Hindari trait yang saling eksklusif. Jika tidak bisa, buat build gagal dengan pesan error yang jelas:
#if TraitA && TraitB
#error("TraitA and TraitB cannot be enabled together")
#endif

Uji setiap kombinasi

swift build build sendiri untuk Mac, dan plugin yang bergantung pada Capacitor hanya build untuk iOS, jadi uji trait melalui Capacitor test app yang dibuat untuk iOS Simulator. Untuk setiap kombinasi (tanpa entri untuk default traits, ['SQLCipher'], ['.defaults', 'SQLCipher'] dan seterusnya), ubah packageTraits di config test app, lalu sync dan build:

bunx cap sync ios
xcodebuild build \
  -project ios/App/App.xcodeproj \
  -scheme App \
  -destination 'generic/platform=iOS Simulator' \
  CODE_SIGNING_ALLOWED=NO

Tambahkan setiap kombinasi ke CI sebagai job tersendiri.

Tetap dukung pengguna CocoaPods

Trait hanya ada di SPM. Jika plugin Anda juga menyertakan podspec, berikan pilihan yang sama melalui subspecs:

s.default_subspec = 'Core'

s.subspec 'Core' do |core|
  core.source_files = 'ios/Sources/DbPlugin/**/*.swift'
  core.dependency 'Capacitor'
end

s.subspec 'SQLCipher' do |sc|
  sc.dependency 'AcmeCapacitorDb/Core'
  sc.dependency 'SQLCipher', '~> 4.10'
  sc.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => '$(inherited) SQLCipher' }
end

Mengatur nama compilation condition yang sama di subspec memungkinkan Anda berbagi satu #if SQLCipher path code. Aplikasi CocoaPods kemudian memilih subspec di Podfile mereka. Capacitor CLI menulis satu pod baris per plugin di dalam capacitor_pods, jadi dokumentasikan baris Podfile tambahan tersebut di README Anda. Cara menggunakan CocoaPods dengan Capacitor 8 menunjukkan di mana baris pod kustom diletakkan.

Keterbatasan

  • Eksperimental. Opsi-opsi ini berada di bawah experimental dan mungkin pindah ke ios.spm.* pada versi major mendatang. Nantikan perubahan nama konfigurasi di masa depan.
  • Swift 6 belum didukung secara resmi. Dokumentasi resmi CLI memperingatkan bahwa mengatur swiftToolsVersion ke 6.0 atau lebih tinggi dapat menyebabkan masalah. Tes seluruh aplikasi, terutama plugin yang menyertakan binary xcframeworks.
  • Hanya iOS. Android tidak memiliki padanan di Capacitor. Plugin menangani Android SDK opsional menggunakan variabel Gradle di variables.gradle atau artifak terpisah.
  • Plugin harus melakukan opt in. Kebanyakan plugin belum mendefinisikan traits. Periksa terlebih dahulu sebelum Anda merencanakannya.

Pemecahan Masalah

Sync gagal dengan pesan “Package traits require an explicit Swift tools version of 6.1 or higher”. Tambah swiftToolsVersion: '6.1' di samping packageTraits.

SwiftPM melaporkan trait yang tidak dikenal. Nama trait bersifat case-sensitive dan harus ada di dalam Package.swift untuk versi yang terinstal.

Fitur masih belum muncul setelah mengaktifkan trait. Reset cache package di Xcode, bersihkan build folder, dan pastikan hasil generate CapApp-SPM/Package.swift memiliki traits: suffix. Mengedit file itu secara manual tidak akan bertahan, karena CLI menulis ulang file tersebut setiap kali sync.

Error pada Swift code setelah menaikkan versi tools. Itu Swift 6 language mode pada package yang Anda kelola. Tambahkan swiftLanguageModes: [.v5].

Konflik nama antar plugin. Sejak CLI 8.4, experimental.ios.spm.packageOptions memungkinkan Anda mengatur symlink atau moduleAliases per plugin. Pelajari lebih lanjut di Panduan troubleshooting Capacitor iOS.

Untuk gambaran SPM yang lebih luas, baca SPM vs CocoaPods untuk Capacitor. Jika Anda ingin cloud build yang sudah menjalankan Xcode terkini untuk proyek SPM, lihat Build Capgo.

Live updates untuk aplikasi Capacitor

Saat bug web-layer sudah live, kirim perbaikannya lewat Capgo alih-alih menunggu berhari-hari untuk persetujuan app store. Pengguna mendapat update di background, sementara perubahan native tetap mengikuti jalur review normal.

Terbaru dari Blog kami

Capgo memberikan insight terbaik yang Anda butuhkan untuk membuat aplikasi mobile yang benar-benar profesional.