Capacitor is a way to create cross-platform mobile and desktop applications.
It can be used to package web apps made with HTML, CSS and JavaScript into native apps that work on Android and iOS (and can be uploaded to their respective app stores), desktop applications via Electron, and also Progressive Web Apps that run in all browsers - targeting all relevant platforms with one code base.
Capacitor itself calls apps built with its help “Native Progressive Web Apps”, meaning that they combine web apps that have characteristics of a Progressive Web App, with native functionality and code.
It is functionally pretty similar to Apache Cordova (formerly known as PhoneGap) which can be viewed as a predecessor to Capacitor but differs in some important areas and technology choices.
Capacitor is built in the open on GitHub as an Open Source project by the team behind Ionic, a “top open source framework for building amazing mobile apps”, where Capacitor it also intended to be used as a solution to build native applications.
Capacitor wraps the web app in a so-called “WebView” that can display web apps inside the native app. It injects a “bridge” into the app running in the webview, that connects the code of the web app and the code of the native part so these can interact.
This way, functionality normally only available to native code can be used in the web app, and native code can interact with the web app running in the webview as well.
For Progressive Web Apps Capacitor provides fallback implementations to native functionality not present - like for example the default “Take a Photo” view on iOS and Android. It is rebuilt with web technology and provides a similar experience to browser users. This way the web app can provide functionality even when running in a normal browser, that is normally only available to native applications.
Capacitor achieves true cross-platform and portable functionality with 100% code sharing by providing a consistent API, @capacitor/core
, to the web app. Any web app can integrate @capacitor/core
as a normal import
or even a “bundled web runtime” called capacitor.js
that is just included via a <script>
tag.
No matter if the app runs on iOS, Android, in a browser on a mobile device or normal computer - the provider of some functionality is always identical to the web app and all the complexity is taken care of by Capacitor in the background.
A much, much more comprehensive and deeper look at how Capacitor works from a technical point of view can be found over here.
Native Progressive Web Apps built with Capacitor can be used on all the relevant platforms:
Capacitor defines which platform versions are supported when creating the native project:
Capacitor contains a fixed set of platforms that can be added to projects and doesn’t provide a system to dynamically load external platforms “definitions”. To add an additional platform, Capacitor has to be adapted and changed.
Providing native functionality to the web app is Capacitor’s main job. Because of that it includes a multitude of native functionality out of the box:
This list is currently still highly in flux as new APIs and plugins are added according to user feedback all the time. Missing anything? Go create an issue on GitHub.
There are also multiple ways to extend that functionality yourself: You can add custom native code to the native projects or install reusable Capacitor plugins or even existing Cordova plugins with npm
.
The quickest way to add native code to your app is to write “local plugins” that are included in your native project. For both Android and iOS it is as simple as adding 2 files to your project to make native code accessible to the webview, which then can simply be called from the web app.
Capacitor also has a way to package these native modifications into reusable Capacitor plugins. Those can be published as npm packages, so other people can easily download and install them into their own projects. Of course, they can also provide their own “web fallbacks” so the plugins work in the browser in PWAs as well.
As Apache Cordova has a flourishing plugin ecosystem (more than 3000 plugins actually!), the developers of Capacitor decided to also support Cordova plugins. Installation is a bit different as Capacitor doesn’t normally modify the native project files, but many plugins still work and can be used.
Working with Capacitor is mainly done via its Command Line Interface, or CLI, called @capacitor/cli
and executed via npx cap
. It is used to create
or init
projects, add
the native platforms and copy
the web app or update
plugin code to the native project. It is a local CLI bundled with each project, so different CLI versions in different projects are possible.
I also wrote a much more detailed Overview of the Capacitor CLI, @capacitor/cli.
While Capacitor already supports many of its planned use cases, in other areas there exist only plans and not much to look at yet:
While Capacitor was started and is (currently) mainly built by Ionic staff, it is an Open Source project built on the philosophy to work with any web app - not just ones built with Ionic. Any web app that has an index.html
file as its entry point can be packaged with Capacitor.
Ionic will probably add Capacitor to Ionic’s CLI as the default tooling for building native applications when Capacitor is stable enough and can support all the necessary use cases that are currently covered by Apache Cordova.
Ionic Framework is one of the, or the, most popular “user(s)” of Apache Cordova. Each developer packaging their Ionic app as a native app installs Cordova via npm install -g cordova
and uses it to build the native iOS and Android apps with ionic cordova build ios|android
- so the download numbers of Ionic and Cordova are tightly coupled, and Ionic contributes quite a lot to them.
But Cordova was started almost 10 years ago, was still called Phonegap back then, and a lot has changed in the meantime:
It became clear which native platforms are here to stay (not Palm webOS, tizen, FireOS, Blackberry, Firefox OS or Windows Phone - which Cordova all supported at their time), what native functionality all the remaining operating systems offer their users and which of these the users actually want to use. It also became apparent which problems the choices made by the early Cordova developers were causing for developers today.
The biggest change only happened in the last few months when mobile and desktop browser got better support for Progressive Web Apps and Web Components got standardized and implemented. This enabled browsers to become their own, proper platform to be considered to roll out apps. And Cordova is just not set up to support this.
That being said, Apache Cordova of course will not go away - in general and also in Ionic CLI. Capacitor might become the “Successor to Cordova”, or it might just become an alternative for slightly different use cases.
To understand better why Ionic decided to build Capacitor instead of building further on Cordova, it makes sense to take a deeper look at: The differences between Capacitor and Cordova. (To summarize: No global CLI, built-in PWA and web support, but also technical details like the non-existence of a deviceready
event the app has to wait for.)
While not the most important developing facing features, there are some more very interesting details worth to know about Capacitor:
In Capacitor the native projects it creates and you customize are treated as so-called “source artifacts”. That means that once a project is created, you keep it an check it into source control. Capacitor will not (or as little as possible) mess with it anymore, so it is a fully independent piece of code.
Capacitor is built with Swift on iOS by default, but Obj-C can still be used for plugins and custom native code if you want to. Android is all written in Java, but Kotlin is also supported if that is more your style.
Capacitor is structured as one big “monorepo” which contains all the parts (@capacitor/cli
, @capacitor/core
, the native libraries for iOS and Android, a development project, the plugin and platform templates, even the website and docs) versus one repository for each component or part of the whole solution, as many other highly complex libraries like Cordova are organized.
Did I miss anything? Let me know in the comments below and I will update the article as quick as possible. Thank you.