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.

Legacy Cordova:
  • plugin.xml (The monolith)
  • Global cordova.exec()
  • Objective-C (.m/.h)
  • Implicit class loading
Modern Capacitor:
  • 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

  1. 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).
  2. Permission Handling: Capacitor has a dedicated checkPermissions() and requestPermissions() flow that is much more granular than the old Cordova "check on call" approach.

Comments

Popular posts from this blog

How to Compare Strings in C#: Best Practices

Do You Really Need Advanced Algorithms to Be a Great Developer in 2025?

Advanced Chrome Dino Game (HTML + JS + Sprites)