Are Capacitor Applications Native Applications?
The short answer is that a Capacitor application is a native application. No different to a native application built with the native languages for iOS and Android. The difference is what is inside of that native application, and that is where it gets a little harder to explain the difference. This will be the goal of this lesson.
The Problem with Native Applications
The big problem with what some people might call “true” native applications - those built specifically for just iOS or just Android using the platforms native languages - is that you can only target a single platform. If you want to support iOS and Android then you need to maintain two completely separate codebases written in two completely different languages.
Naturally, some solutions to this “problem” started to emerge. These came in different flavours and have had varying levels of adoption over the years. The most popular approaches today are:
- Cordova/Capacitor (we will be focusing on Capacitor)
- React Native
What is a Hybrid Application?
Cordova, which Capacitor is meant to be the successor of, popularised the concept of a “hybrid” application. A “standard” or “pure” native application (i.e. those written with the native language of the platform) look something like this:
We have a native application, and inside of that native application we use native controls to render the user interface for the application - things like native lists, tabs, buttons, and so on.
A “hybrid” application looks something like this:
The cool thing about this approach, is that we can then just load that same content inside of another web view on any other platform:
Our application also isn’t limited to just the web view either. Again, a Capacitor application is just a normal native application, so if we want to we can still add normal native controls to it. Most of our application lives inside of the web view, so generally it is easier to have most of what is going on in the application within the web view. But, if we want to for some special circumstances, we can launch whatever kinds of native views we like. We can also make calls to whatever native APIs we want from within our web view as well.
What’s the catch?
The description above could sound like Ionic and Capacitor is the perfect solution, why would you ever use anything else?
The mere existence of other solutions like React Native and Flutter, and that people still do build applications with the native language for iOS and Android, implies that this Ionic/Capacitor approach is not the holy grail of all mobile development.
As is always the case, different approaches have their pros and cons. I will focus on the most common for and against arguments for the Capacitor approach. It’s worth keeping in mind that people can get especially dogmatic when it comes to “native” vs “hybrid” applications and everything in between. It’s not hard to find articles from people who are invested in one tech stack to write off the others as inferior or worthless. All of the approaches I have mentioned are highly popular today because a lot of people are using them because the pros of that particular approach work for them. Anybody who tells you that a particular approach is stupid, or worthless, or pointless, or whatever else is either lacking in knowledge or perspective… or is just being straight up dishonest.
Obviously I like Ionic/Capacitor, so keep that bias in mind for the next section! I am going to intentionally try to focus a little more on the cons.
The Pros of Capacitor
Many of the cross platform approaches achieve some level of code reuse among multiple platforms, but the approach of using a web view to display your application means we can often achieve the goal of having 100% code reuse. It is possible to make platform specific customisations with Capacitor, but these are usually minor if they are present at all.
Although Capacitor allows for modifying the native code if you wish, you can build an application entirely with just web tech
More people use web views than you might think. Even more traditional “pure” native applications still use web views for parts of their application - Instagram for examples renders parts of its UI using web views. Using web views isn’t something for low-end prototype applications, many big name applications utilise web views.
The Cons of Capacitor
With Capacitor, we have a normal native application with a web view control inside of it. But, code running inside of that web view can not directly access native functionality. Instead, we have to use Capacitor as a “bridge”. Our web code makes a call to the Capacitor bridge, and the Capacitor bridge passes this message on to the native APIs (and also gives us data back if required). If we need to do computationally intensive stuff, or maybe make use of some Native SDK, we can do that in “native land”. We can open up a native view or we can communicate data back to our application inside of the web view. But this can be awkward. If we want to display a native view for example, it is not going to be well integrated into the flow of our user interface. We will generally have to popup a modal style view on top of our web view which might not be the experience you want. Although we can integrate normal native experiences into our web application, there is some level of unnaturalness to it.
We aer mimicking the native controls with web implementations rather than using them directly. Ionic does an amazing job of recreating the native controls using web tech. Without Ionic or a similar UI framework, the quality of Capacitor applications would not come near native iOS and Android. Building these things from scratch yourself is hard (even building a list that scrolls smoothly is not an easy task). But, no matter how great the Ionic components are, they are still an imitation not the “real deal”. For me and many others, directly mimicking the exact look/feel/style of iOS/Android is not that important. But, for some people, that is important. If your application is targeting people who are super into those sorts of details then that might be important.
The part of our application running inside of the web view, which is generally most of it, is powered by a browser - unlike the native controls and logic that are powered by the native platform directly. I think this is often played up for more than it’s worth. Just like how most people don’t need a Ferrari if all they are doing is city driving, the vast majority of applications can be powered just fine by modern web tech. In the past, browsers were not as powerful and this was a bit more of a concern, but unless you are doing something particularly animation heavy or computationally expensive any difference in processing power is going to be negligible. It’s also important to keep in mind that just because something is “native” it doesn’t make it better. A well coded Capacitor application is going to outperform a poorly coded native application.
Playing catchup. If you are building with native iOS/Android directly, then you instantly have access to any new features or approaches. If something drastic changes, and you are using Ionic/Capacitor, then you are going to have to wait on Ionic/Capacitor to support that thing (or workaround it by building it yourself). This isn’t generally an issue since there usually aren’t massive changes, and the Ionic/Capacitor team are quick to update anyway, but still it’s a consideration.
Relying on the community. There are many plugins available for Capacitor created by both the Ionic team and the community that provide various native integrations. However, if you are using any of the non-official plugins, you are relying on the community to maintain this plugins. Often, these plugins are provided by a single person volunteering their time to provide something for the community and they can’t be expected to keep it constantly updated. There is also the possibility that there is no plugin available for the native functionality you need. This would mean that you have to integrate that native functionality with Capacitor yourself using native code. I don’t know if this is really a downside, because if you weren’t using Capacitor then you would be doing everything in native code yourself anyway. However, it can certainly lead to situations where you assume you will have everything you need and be able to do it all with web tech, and then you get blocked because you need native functionality that doesn’t exist in Capacitor and you don’t know how to implement it yourself.
In the following lessons, we are going to focus on learning the basic concepts of Capacitor - with or without Ionic.