Im Mai dieses Jahres gab das Ionic Framework Team die Veröffentlichung des Open-Source-Projektes Capacitor bekannt und leitete damit eine kleine Revolution in der hybriden App-Entwicklung ein. Capacitor ist ein nativer Container, mit dem webbasierte Apps auf Android, iOS, Deskop und im Browser ausgeführt werden können.
Jeweils mit vollem Zugriff auf die jeweiligen nativen Schnittstellen und Möglichkeiten. Capacitor ist vergleichbar mit Cordova/Phonegap, nur um ein Vielfaches besser. Capacitor ist Cordova in modern. Das Ionic Team hat echte Arbeit geleistet, um den hybriden Entwicklungsprozess zu vereinfachen und zu optimieren.
Capacitor kann als eigenständiges Tool genutzt werden, um beliebige Web-Apps für die jeweiligen Plattformen bereitzustellen. Capacitor ist aber auch direkt in Ionic integriert. In Zukunft hat man also die Wahl zwischen Ionic/Cordova oder Ionic/Capacitor, wobei die Weichen klar auf Capacitor gestellt sind!
Die Probleme von Cordova
Welcher Ionic-Entwickler kennt nicht die alltäglichen Probleme bei der Erstelung hybrider Apps mit Cordova. Cordova ist ein gewachenses System zur Erstellung eines nativen Containers für webbasierte Apps, das einige strukturelle Mängel und Probleme aufweist. Und uns Entwickler manchmal an den Rande der Verzweiflung treiben kann. Sämtlicher Zugriff auf native Funktionen, wie Kamera, Bluetooth, Push-Notications oder allgemeine App-/Geräteinformationen müssen über einzelne, meist über Drittanbieter/Community entwickelte Plugins hinzugefügt werden. Plugins die gegenseitig Probleme bereiten können, bleiben dabei nicht aus.
Für Ionic Apps muss neben dem grundlegenden Cordova-Paket auch die jeweilige Plattform (iOS/Android) als Paket hinzugefügt werden. Das bedeutet sehr viele (Paket-)Abhängigkeiten, unterschiedliche Versionen und damit verbundene Versionskonflikte. Dazu kommen noch die Abhängigkeiten zu Node.js und der jeweilig nativen Toolkette (Xcode mit Command Line Tools, Android Studio, Android SDK,…). Die Kompilierung, das Starten der App auf Emulatoren und Endgeräten muss über die Cordova CLI ausgeführt werden, wobei es bei Inkompatibilität der unterschiedlichen Systeme und Pakete immer mal wieder zu zeitraubenden Problemen kommen kann.
Die Konfiguration der einzenen Plattformen (Berechtigungen, Ressourcen, Umgebungsvariablen, Entitlements,…) müssen über eine Cordova-spezifische Konfigurationsdatei (config.xml) definiert werden. Auch hier kann es immer wieder zu Problemen und Überschneidungen kommen. Und wer schon einmal versucht hat, ein externes natives Framework (wie zum Beispiel OpenCV) als Cordova-Plugin einzubinden, weiß welche Höllentäler ein Entwickler manchmal durchschreiten muss. Inbesondere der Zugriff auf individuelle, native Funktionalitäten ist über Cordova ein Graus.
Aber wir möchten uns nicht nur beschweren: Cordova hat uns und vielen Entwicklern über Jahre und vermutlich auch noch weiter einen guten Dienst geleistet. Doch nun geht es halt besser und einfacher.
Der „Capacitor Way of Development“
Das Ionic Team hat sich diesen Problemen angenommen und mit Capacitor einen ganz neuen Weg der hybriden App-Entwicklung eingeschlagen. Capacitor stellt zu einem Web-Projekt einen nativen Container mit allen grundlegenden API-Zugriffen bereit. Beide Welten, natives Rahmenprojekt und webbasierter Kern, existieren dabei gleichberechtigt nebeneinander. Alle nativen Konfigurationen, Einstellungen und Erweiterungen können/müssen direkt in Xcode oder Android Studio vorgenommen werden.
Das Kompilieren, Installieren und Testen auf Emulatoren/Endgeräten erfolgt dabei direkt in den nativen Entwiclungsumgebungen. Damit müssen sich hybride App-Entwickler zwar etwas detaillierter mit Xcode und Android Studio beschäftigten, die deutliche Vereinfachung der gesamten Toolkette dürfte aber diesen kleinen Nachteil bei Weitem aufwiegen.
Aber schauen wir uns an, wie die Vorgehensweise einer Ionic-Entwicklung über Capacitor aussieht…
Erste Schritte mit Ionic und Capacitor
Capacitor erstmalig einrichten
Starten wir ein kleines Projekt von Grund auf und schauen uns die benötigten Befehle beim Einrichten eines Ionic-Capacitor-Projektes an:
ionic start myTestApp
ionic integrations enable capacitor
npx cap init myTestapp my.test.app
ionic build
npx capp add ios
Bevor wir eine Plattform hinzufügen müssen wir das Projekt einmalig erstellen/kompilieren (4), danach können wir beispielsweise ios (oder android) als Plattform (5) hinzugefügen.
Capacitor erstellt dabei im Root-Verzeichnis des Projektes einen Ordner ios (oder android) und darin ein eigenständiges Xcode-Projekt, das eine Kopie der webbasierten App enthält. Anders als in Cordova, muss der native Ordner ios/android auch mit in die Versionsverwaltung übernommen werden, da wie bereits erwähnt alle native Konfigurationen und Erweiterungen direkt dort vorgenommen werden.
Änderungen in der Webapp übernehmen
Ändert sich etwas im webbasierten App-Code, muss dieser neu erstellt und in das native Projekt synchronisiert werden:
ionic build
npx cap copy
Native Entwicklungsumgebung öffnen
Das Projekt kann dann direkt in Xcode (oder Android Studio) manuell geöffnet und auf Emulatoren/Endgeräten ausgeführt werden. Alternativ kann das Xcode-Projekt über die Kommandozeile geöffnet werden:
npx cap open ios
Danach kann das Projekt ganz normal in Xcode kompiliert und auf Emulatoren/Endgeräten getestet werden.
Und was ist mit Live-Reload?
Das manuelle Kompilieren der Web-Anwendung und die Synchronisierung erscheint im Gegensatz zu Cordova als etwas aufwändiger. Der Schritt wird aber eigentlich kaum, bzw. nur in der Endphase beim endgültigen Deployment benötigt. Während der Entwicklung kann zeitsparend wie in Cordova gewohnt per Live-Reload entwickelt werden.
Und dank der Vereinfachung der Toolkette auch deutlich weniger fehler- und problemanfällig. Dazu muss einfach über die Kommandozeile der Live-Reload-Server gestartet werden:
ionic capacitor run ios -l --address=0.0.0.0
Danach kann das Projekt direkt in Xcode auf Emulatoren/Endgeräten gestartet werden, die Live-Reload-Funktion ist automatisch aktiv. Ein schnelles Wechsel zwischen Emulatoren über Xcode inklusive.
Es müssen weder Target-Namen oder -Ids von den unterschiedlichen Emulatoren über die Kommandozeile ermittelt werden. Noch muss zwischen dem Native-Run-Modul von Ionic und Cordova (Stichwort –no-native-run) gewechselt werden, weil einer der beiden Möglichkeiten wieder mal inkompatibel mit den installierten Paketen, bzw. der Systemumgebung ist.
Ein Klick auf den Play-Button in Xcode reicht. Jawohl, hybride Entwicklung kann auch Spaß machen!
Zugriff auf native Funktionen und Erweiterungen
Nativer Zugriff „Out Of The Box“
Capacitor beinhaltet alle grundlegenden Schnittstellen zu den nativen Funktionen, seperate Plugins wie bei Cordova werden nicht benötigt. Folgende Grundfunktionalitäten können in Capacitor unter anderem direkt genutzt werden:
- App
- Background-Tasks
- Camera
- Device
- Local Notifications
- Modal
- Motion
- Network
- Push Notifications
- Storage
- …
Beispiel: Zugriff auf Kamera
import { Plugins, CameraResultType } from '@capacitor/core';
const { Camera } = Plugins;
async takePicture() {
const image = await Camera.getPhoto({
quality: 90,
allowEditing: true,
resultType: CameraResultType.Uri
});
var imageUrl = image.webPath;
imageElement.src = imageUrl;
}
Es wird kein zusätzliches, externes Plugin von Drittanbieter benötigt.
Und das Beste: Dieser Code funktioniert auf iOS, Android, im Desktop über Electron und sogar im Browser. Write once, run everywhere!
Individueller nativer Code
Wer schon einmal unter Cordova versucht hat eigenen nativen Code über Cordova-Plugins in das Projekt zu integrieren, weiß um die Probleme und Komplexität. Einen schönen Gruß aus der Entwickler-Hölle. Doch mit Capacitor gibt es auch hier einen Lichtblick: Individueller nativer Code kann extrem einfach in das eigene Projekt integriert und im Javascript-Code genutzt werden.
Dazu muss im nativen Projekt in Xcode lediglich eine beliebiege Swift-Datei, z.B. myNativeCode.swift erstellt werden:
import Capacitor
@objc(MyNativeCode)
public class MyNativeCode: CAPPlugin {
@objc func echo(_ call: CAPPluginCall) {
let value = call.getString("value") ?? ""
call.success([
"value": value
])
}
}
Im Anschluss muss lediglich in einer gleichlautenden Objective-C-Datei (ohne Header-Datei) MyNativeCode.m nur noch die neue Funktionalität registriert werden:
#import <Capacitor/Capacitor.h>
CAP_PLUGIN(MyNativeCode, "MyNativeCode",
CAP_PLUGIN_METHOD(echo, CAPPluginReturnPromise);
)
Und schon kann in Javascript auf die native Funktion zugegriffen werden. Einfach und flexibel. Damit können in einem Ionic-Capacitor-Projekt auch Webentwickler und native App-Entwickler Hand in Hand parallel an einem Projekt arbeiten. Benötigte externe Frameworks oder SDKs können direkt in der nativen Umgebung eingerichtet und genutzt werden.
So einfach und flexibel kann hybride App-Entwicklung heute sein!
Das Beste kommt zum Schluss: Cordova-Plugins können weiter genutzt werden
Das Ionic Team hat hervorragende und sehr entwickler-orientierte Arbeit geleistet. Capacitor ist voll abwärtskompatibel zu Cordova. Der Vorteil von Cordova ist die lange Geschichte, der großen Community und die damit goße Verbreitung von Plugins. Und auf diese Vorteile muss bei der Capacitor nicht verzichtet werden. Cordova-Plugins können direkt in Capacitor eingebunden und genutzt werden, ohne auf den vereinfachten Entwicklungsprozess verzichten zu müssen. Um ein (externes) Cordova-Plugin verwenden zu können, müssen lediglich folgende Befehle eingeben werden:
npm install cordova-plugin-scanbot-sdk
npx cap sync
Die Typescript-Implementationen von Ionic Native können natürlich ebenso verwendet werden:
npm install cordova-plugin-applepay npm install --save @ionic-native/apple-pay npx cap sync
One more thing…
Ach fast hätten wir noch was vergessen. Mit Capacitor können nicht nur iOS- und Android-Apps, sondern auch Desktop-Apps und Progressive Webapps. Ohne weitere Plugins oder Zusatzmodule werden mit einem Quellcode folgende Plattformen mit den jeweiligen nativen Schnittstellen unterstützt:
- iOS
- Android
- Desktop Apps für Windows, Mac und Linux über Electron
- Progressive Webapps
Das Fazit der App-Agentur:
Capacitor und Ionic bündelt nun wirklich das beste aus beiden Welten. Aus der nativen und webbasierten Welt. Der Entwicklungsprozess für hybride Apps wurde extrem vereinfacht, Abhängigkeiten wurden gelöst und der Zugriff auf native Funktionen optimiert. Webentwickler und native Entwickler können endlich wirklich parallel in ihrer Welt Hand in Hand an einem Projet arbeiten.
Neue Funktionen und Updates der nativen Entwicklungsumgebungen direkt genutzt werden. Die Geschichte der hybriden App-Entwicklung hat neu begonnen. Es gibt keinen Grund Capacittor nicht zu nutzen.
Write once, run everywhere!