What is Capacitor?

Capacitor is a cross-platform app runtime that makes it easy to build web apps that run natively on iOS, Android, Electron, and the web. It was created -and is maintained- by the Ionic Framework team. The first stable version (1.0) was released at the end of May 2019.

In this post I will try to give you a good introduction about what Capacitor is and why did the Ionic team create it. Also, we will go through the main differences between Capacitor and Cordova and get to know more about Capacitor plugins. We will be also talking about the migration strategy, why should you consider migrating and what's involved at a high level in the migration.

As a side note, I want to tell you that I did the migration to Capacitor of our latest Ionic 4 starter app and it was super easy and straightforward. I did not experience any issues and I’m super happy with the new app structure without Cordova. So, without further ado, let’s start!

Capacitor provides a consistent, web-focused set of APIs that enable an app to stay as close to web-standards as possible, while accessing rich native device features on platforms that support them.

With Capacitor, adding native functionality to our apps can be easily done using a simple Plugin API for Java on Android, JavaScript for the web and Swift on iOS. We can say that Capacitor is a spiritual successor to Apache Cordova and Adobe PhoneGap.

It's important to mention that Capacitor can work with any web project, it’s not Ionic specific, and is version independant (works with Ionic v1 to v4 and anything that comes in the future). It can be used as a drop in to any existing modern JavaScript project.

Capacitor has a "Code once, configure everywhere" mantra and in this post we will explain why.

How does Capacitor fit in the app development ecosystem?

What is Ionic Framework?

In case you're kind of new to Ionic Framework, let me give you a quick intro. It’s a mobile-ready and cross-platform UI library and toolkit that works everywhere; any platform, any device, any framework. You can reuse your existing web skills; HTML, CSS and JavaScript to build apps for IOS, Android, Electron and PWAs. You can create one codebase that can go across all these platforms just using your web skills and target the different native APIs and features, like Geolocation, Camera, Bluetooth.

If you are new to this world I suggest you to read more about Ionic's key components. Also, when it comes to PWAs, we wrote a Complete Guide To Progressive Web Apps with Ionic 4 that you may want to bookmark for a future reading because we deeply explain what are PWAs, why you should definitely consider them for your next project, and also show how easy is to build a feature complete PWA with Ionic 4!

What are hybrid Applications?

An Hybrid Application is a web app built with the web skills you already have, and then packaged inside of a real native app shell. With this approach you get full access to all the different device functionalities while your Ionic or Web app is running inside of a web-view within that native app. For end users it will still be a native app, enabling you to run your code everywhere and reach potentially millions of users.

What about Cordova?

Up till now, Phonegap or Cordova, (they're basically synonymous) has been the native wrapper for Ionic apps.

The team behind Cordova created it in 2008. Cordova really helped developers with web skills that wanted to reuse them and, especially get onto the exciting mobile platforms that everyone has these days.

Cordova’s mantra is "Write once, Run everywhere", and that's what Ionic has been all about since the beginning. Cordova is fully open source and backed by a great community but lately it had some challenges keeping up to date with the latest changes of the native platforms. iOS and Android are constantly undergoing different changes, whether that's new operating system updates or new hardware. These affects Cordova and any Ionic app as well. That’s why the Ionic team had to keep up with these kinds of things and move fast to ensure that they were deploying and supporting these different features.

And also, on the more native side of things, more modern plugin system capabilities with Cocoa Pods and Gradle which are dependency management tools that hasn't been supported by Cordova. As well as wanting to use more modern native languages, like Swift and Kotlin. So, the team at Ionic thought, it was a good idea to create a spiritual successor to Cordova that could use all these modern native tools and provide just really an overall better developer experience. And their solution to that is Capacitor. So, let's dig into what that looks like.

If you want to start creating your Ionic Framework app but don’t know how to start, I suggest your to try Ionic 4 Full Starter App. It’s an ionic 4 app that you can use to jump start your Ionic Framework development and save yourself hundreds of hours of design and development.

It includes more than 100 carefully designed views and components. It has full support for PWA with Angular. Try it on your phone as a native app or as a PWA to see the magic!

Welcome Capacitor to the Ionic Ecosystem

At the end of the day, Capacitor has the same type of goals as Cordova.

Capacitor is a cross-platform runtime created by the Ionic team that allows you to target different types of native platforms like iOS, Android, the desktop using Electron and the Web. Traditionally, Cordova has had bad support for the web but Ionic promises to solve this with Capacitor.

Capacitor has first-class support for Progressive Web Apps and native apps. That means that Capacitor's plugin bridge supports running in either a native context or in the web, with many core plugins available in both contexts with the exact same API and calling conventions. This means you'll use @capacitor/core as a dependency for both your native app and your Progressive Web App, and Capacitor will seamlessly call web code when required and native code when available.

The ability to have multiple implementations for an API is a clear benefit of Capacitor because, let's say we want to use the Camera plugin, the installed native app will use the native implementation while the PWA will use the web implementation, all with the same codebase.

How does Capacitor plays with Cordova?

For the majority of plugins today, Capacitor has full backward compatibility. However, there are some of them that don't work for various legacy technology reasons.

One of the things Capacitor wants to do is staying as close to the native browser capabilities as possible. This will allow them to ensure a great stability and maintainability because by staying close to the web standards, they can ensure that things will work for a long time to come. And this is a very important point for us as developers.

Capacitor’s mantra is "Code once, Configure everywhere". And this is because they are embracing more of the native modern tooling, which they claim it will help us maintain our projects a lot easier than in the past with Cordova.

What are the differences between Cordova and Capacitor?

There are two main major points when doing a Capacitor VS Cordova comparison: Native Project Management and Plugin and CLI Management. Let’s go through each of them to see the main changes and their benefits.

Native Project Management

Using Capacitor will result in some interesting architecture design changes, comparing to what we were used with Cordova, but the Ionic team believes this will serve everyone well for the long-term. Let’s see why.

Change #1 - source assets versus build time assets

Capacitor trates the native projects that are generated such as iOS, Android, Electron, as code that you actually check in and maintain and they're essentially first-class citizens in that sense.

This is a clear benefit comparing with Cordova, where when you're interacting with the native projects that are generated, for example to add plugins, or to make changes, they can get wiped away or end up in different states of use and this can be hard to maintain.

Another benefit of having real native projects is that it makes it easier to add custom native code to them. You just need to open the project into its native IDEs and make the changes you need without having to do this through a plugin.

Also, another benefit is the ability for native mobile teams to work with web teams, because you no longer have a conflict where both teams are making changes in the same files. They're separate web and native projects, so you can be developing over time.

Change #2 - Custom configurations

Capacitor is pushing us towards using the platform’s specific IDE; Xcode for iOS and Android Studio for Android. This means no longer we’re going to have an abstracted layer, which today for Cordova is config.xml. So, the benefit here is that by not having that abstraction over the native layers, it gives us far more control and visibility into the native project changes and overall leads to a better experience maintaining apps over time.

All of us have probably run into situations where you come back to an app after some time and try to rebuild it and update all the dependencies, and just have it simply not work or not build in the first place. So, Capacitor is trying to make that experience a lot smoother and better for us.

Also, another benefit is that if you do run into native issues, such as built or configuration issues, it'll be much easier to troubleshoot because we can have direct access to the native projects and therefore, searching online in different forums for that specific problem.

Change #3 - Use Platform Specific IDEs

The Ionic Team behind Capacitor ensures that by embracing the native platform IDEs it will just lead to a better experience for everyone.

Plugin and CLI Management

We also have plugin and CLI (Command Line Interface) management changes.

Change #1 - Built as Frameworks (iOS) and Libraries (Android)

The main change for plugin development and maintainability is building them with more modern capabilities, as frameworks on iOS and Libraries on Android. There are a lot of different things that go into that. For example, you no longer have to copy plugin files directly into your project and in fact, they're full fledge libraries and just code that can be developed outside your Ionic app.

Plugins in Capacitor enable JavaScript to interface directly with Native APIs. When it comes to working through and creating your own plugins, Capacitor has a great plugin generation command and other tooling that is explained in the documentation. Capacitor auto generates JavaScript hooks on the client, so most plugins only need to build a native Java plugin for Android and a Swift/Obj-C one for iOS. Using the CLI to generate your own Capacitor plugins is very easy.

One of the benefits of using this approach, is to have less error prone plugins and to make it easier to find help in the community for each platform when you're working on troubleshooting plugins.

Change #2 - Registers and exports all JavaScript for every plugin at runtime

Additionally, Capacitor registers and exports all JavaScript for each plugin based on the methods it detects at runtime. This means that all of your code is available right away at runtime when your app starts out. So, no more need for the device ready event, which if you've worked with Cordova, you've probably run into that issues with trying to use different plugins right away and having your app crash or not work well and being confused about that.

Change #3 - Capacitor CLI gets installed locally into each project

Cordova typically gets installed globally on your machine while the Capacitor CLI gets installed locally into each project. This makes it easier to manage different versions of Capacitor across all of your different apps.

Migration Strategy. Should you migrate?

The first thing to mention is that the migration isn't compulsory so you are free to choose what you want to do with your project. The effort involved in the migration will largely depend on the complexity of the app but you can do it progressively over time so there’s no rush and also no reason to freak out.

Also, it's important to mention that Capacitor isn’t specific to Ionic projects, it works with all web projects.

Migrating from Cordova to Capacitor can occur over time or can be fully replaced in many cases. The effort involved will largely depend on the complexity of the app.

If you have an existing app that's using Cordova, let's talk a little bit about the migration strategy. So, why migrate? What's involved at a high level?.

It's really about long-term stability and peace of mind.

Now, that the Ionic team released this tool, we can expect updates and releases a lot quicker than the Cordova ecosystem.

Also, remember we mentioned that Capacitor has Cordova backward compatibility so adding it to a Cordova project should just work and you get all the benefits of working with native projects.

The Ionic team has been a long-term open-source contributor to the Cordova community and they say that this isn’t going to change for a long time to come. So, no worries, you can still stay using Ionic Framework + Cordova if you don’t want to change. But that said, we do feel that Ionic and Capacitor are the future for building modern web apps and cross-platform hybrid apps.

Should you migrate? My personal opinion

As we mentioned above, there are differences that Capacitor has over Cordova both regarding the Native Project Management and the Plugin and CLI Management. And I think that these differences and new approaches can be either a benefit or an opportunity for you, depending on your background and your current development skills. Let me explain why.

If you choose to migrate to Capacitor, it's important you understand that you will be dealing directly with the native platform (ios or android), their specific configurations, issues, errors, community, building processes, IDEs, languages, and their own specific concepts. Capacitor requires you to be a lot more involved in the native project configuration than with Cordova so at the end of the day, if you are a web developer with no native skills, it's up to you if you want to invest the required time and effort in learning these new concepts.

On the other hand, if you are a native developer you will love working with Capacitor because you will be working directly with the native apps. So for native devs it will be a no brainer decision.

I know many people started using Ionic Framework because they were web developers wanting to create mobile apps, myself included. Capacitor brings us the opportunity to expand our knowledge on mobile apps inducing us to learn these new concepts and I think this is great. But if you are afraid to make the change now, or you don’t have the time to invest in learning this new flow, it’s totally fine. You can do it when you are ready. Ionic apps will continue to work with Cordova in the same way they worked before Capacitor.

So, to sum up, migrating your Ionic app from Cordova to Capacitor has both pros and cons (or as I like to see them, opportunities). It brings a lot of benefits when building cross platform web apps, it’s based in a “Code once, configure everywhere” philosophy, it’s optimized for Ionic Framework apps, but, migrating is not a must, it can be done over time, the effort depends on the complexity of your app and, if you have no native skills, it requires you to invest time and effort to get into these new workflows.

That's why we have decided that for our Ionic 4 templates, we will provide both options so people can choose what suits best for them. When you get one of our ionic 4 starters you will find the same app configured both with Cordova and another one with Capacitor.

Cordova to Capacitor migration process

Capacitor has some dependencies depending on which platforms you're targeting and which operating systems you are developing on. So I suggest you to go through this document first.

There are two ways to start using Capacitor: adding Capacitor to an existing frontend project (recommended), or starting a fresh project. To use Capacitor with Ionic Framework you need to run the following commands from the console inside your Ionic app. First run:

ionic integrations enable capacitor

Then, you need to Initialize Capacitor with your app information which will create a capacitor.config.json file. To do this just run:

npx cap init [appName] [appId]

Where appName is the name of your app, and appId is the domain identifier of your app (ex: com.example.app). In cordova apps you had this id in the config.xml file. You can use the native IDEs to change these properties after initial configuration.

Note: npx is a new utility available in npm 5 or above that executes local binaries/scripts to avoid global installs.

Now you need to build your Ionic project before adding any native platforms because this will create the www folder that Capacitor has been automatically configured to use as the webDir in capacitor.config.json.

Now you are ready to add the platforms to your project by running:

npx cap add ios npx cap add android

This will create an ios and an android folder (respectively) at the root of the project. These are entirely separate native projects that should be considered part of your Ionic app, this means you need to check them into source control and edit them in their own IDEs.

Let me show you how the code structure of our Ionic 4 starter template changed with the Cordova to Capacitor migration. The one in the left is with Cordova and the one in the right is without Cordova and with Capacitor.

Code structure with Cordova
Code structure with Capacitor

So at this step you had enabled and configured Capacitor into your Ionic project and added the ios and android platforms. Now, it’s time to run this new native apps! To do this we will use the Native IDEs so, we will use Xcode for iOS and Android Studio for the android app. We will use these IDEs to run and deploy our apps. Luckily, the CLI has a command to open them:

npx cap open ios npx cap open android

It’s important you remember that every time you perform a build (ionic build) that changes your web directory (www), you'll need to copy those changes down to your native projects by running the following command:

npx cap copy

Make sure to follow the Development Workflow documentation so you don’t get in any issue.

That’s all for a basic Ionic app without Cordova plugins. We saw how easy it was to add Capacitor to an existing Ionic app but if you are currently using any cordova plugin, I recommend you to take the time to audit your list of Cordova plugins you're using today. Take a look and see if you need to use all of them or if there are some that you can deprecate and remove from your project. Then for the ones that remain, start to migrate them over one by one.

There are a bunch of the core APIs that were built by the Ionic team, and then the community has been contributing with lots of different plugins and API's as well.

If there are incompatible ones that aren't working or there are ones that aren’t covered from the core list, don’t worry. Capacitor and Cordova, can work side by side, so continue to use that as well as any Ionic Native plugins and typescript wrappers alongside those. See the Using Cordova Plugins guide for more information.

Now if you want to fully migrate a web app using Cordova over to Capacitor there are several steps you need to follow and are well explained in this guide.

Final thoughts about Capacitor and Ionic

Using Ionic and Capacitor together is the way to build the best app experience possible, since Ionic Framework provides UI and UX enhancements that Capacitor does not have. Additionally, it works with your favorite web app framework, including Angular, React, and Vue.

With the release of Capacitor, Ionic now controls almost all of its stack. When you build an Ionic app today, they now control the native runtime layer (Capacitor), the UI controls (Ionic Framework), and the "framework" used to build the controls (web components powered by Stencil). This is significant because if there’s an issue in any part of the stack that Ionic controls, they can fix it right away. The only part Ionic doesn’t control is the frontend framework you use on top (Angular, React, Vue, or plain JavaScript).

Capacitor embraces this idea of "Code once, configure everywhere" because configuration is managed per-platform instead of in an abstracted system like a config.xml in Cordova. As we saw in this post, this is an important point, because it means that Capacitor requires you to be more involved in the native project configuration than with Cordova. Although it may be scary at the beginning, this approach makes it easy to follow existing Native iOS/Android guides, get help on Stack Overflow, and have full control over your project.

Capacitor has first-class support for Progressive Web Apps and native apps. That means that Capacitor's plugin bridge supports running in either a native context or in the web, with many core plugins available in both contexts with the exact same API and calling conventions. This means you'll use @capacitor/core as a dependency for both your native app and your Progressive Web App, and Capacitor will seamlessly call web code when required and native code when available.

Since Cordova is such a hugely popular framework with a massive ecosystem of plugins to access various native functionality, Capacitor is aiming to have backward compatibility with existing Cordova plugins. This means that if you are using Capacitor, you should be able to use any existing Cordova plugin with it.

Doing the migration from Cordova to Capacitor isn't compulsory so you are free to choose. The effort involved in the migration will largely depend on the complexity of your app but you can do it progressively over time so there’s no rush and also no reason to freak out.

If you want to see an example app built with Ionic 4 and Capacitor you can check Building an Ionic Framework Camera App. Also, the Ionic team also built another great example app using Push Notifications with Firebase in an Ionic 4 Angular App.

Hope this post helped you getting an idea of what Capacitor is and how to start using it to build your apps!