Cordova is Deprecated: A Senior Developer’s Guide to Migrating Plugins to Capacitor
Bridging the gap between the "Plugin.xml" era and Native-First Architecture.
Why the Shift? The Architecture Paradigm Change
For a Senior Cordova Developer, the move to Capacitor isn't just a "version upgrade"—it's a fundamental shift in Source of Truth. In Cordova, your native projects (Android/iOS) were transient build artifacts generated by a CLI. If you touched the code inside /platforms, it would be wiped out on the next build.
Capacitor flips this: The native project is now committed to your repository. You no longer "inject" code; you develop inside the native IDEs (Android Studio/Xcode). This eliminates the "Build Hook" nightmare and gives you 100% control over the native lifecycle.
1. Structural Anatomy: Goodbye plugin.xml
The biggest hurdle for senior devs is unlearning the plugin.xml. Capacitor uses standard package.json dependencies and native manifests.
plugin.xml(The monolith)- Global
cordova.exec() - Objective-C (.m/.h)
- Implicit class loading
package.json(NPM based)- Typed Proxy / Interfaces
- Swift & Kotlin native
- Explicit Plugin Registry
2. Hands-on Migration: The "Hello World" Bridge
Android Migration (Java)
In Cordova, you had to parse JSONArray args manually. In Capacitor, parameters are passed as a JSObject (Key-Value pairs).
// Capacitor Android Implementation
@CapacitorPlugin(name = "HelloWorld")
public class HelloWorldPlugin extends Plugin {
@PluginMethod
public void sayHello(PluginCall call) {
String name = call.getString("name", "Stranger");
JSObject ret = new JSObject();
ret.put("message", "Hello " + name + " from Android!");
call.resolve(ret); // No more callbackContext.success()
}
}
iOS Migration (Swift)
This is where the real benefit lies. Most Cordova plugins are stuck in Objective-C. Capacitor makes Swift first-class.
// HelloWorldPlugin.swift
import Foundation
import Capacitor
@objc(HelloWorldPlugin)
public class HelloWorldPlugin: CAPPlugin {
@objc func sayHello(_ call: CAPPluginCall) {
let name = call.getString("name") ?? "Stranger"
call.resolve([
"message": "Hello \(name) from iOS!"
])
}
}
Important: On iOS, you must also create a .m file (Objective-C macro) to register the plugin to the Capacitor Bridge, even if you write the logic in Swift.
// HelloWorldPlugin.m #import <Foundation/Foundation.h> #import <Capacitor/Capacitor.h> CAP_PLUGIN(HelloWorldPlugin, "HelloWorld", CAP_PLUGIN_METHOD(sayHello, CAPPluginReturnPromise); )
3. The Web Interface (The Bridge)
In Cordova, you'd use module.exports. In Capacitor, you define an interface in TypeScript, ensuring your Web app knows exactly what data to expect.
// definitions.ts
export interface HelloWorldPlugin {
sayHello(options: { name: string }): Promise<{ message: string }>;
}
Senior Check-list for Migration
- Identify Hooks: If your Cordova plugin uses
<hook type="after_prepare" />, you must rewrite this logic using a Gradle script (Android) or a Build Phase script (Xcode). - Permission Handling: Capacitor has a dedicated
checkPermissions()andrequestPermissions()flow that is much more granular than the old Cordova "check on call" approach.

Comments
Post a Comment