Cordova is a framework for developing cross-platform mobile apps using web technology. Develop your application using the technologies you know, deploy to all major platforms without the complications of native development, and tap into a rich ecosystem of plugins for adding native functionality to your app.
Sounds great, doesn’t it? Well, if you have used Cordova before, you may have found the harsh reality of Cordova development to be at least sometimes a bit more gloomy that this. As for us: we use Cordova for delivering a web application as a standalone mobile app for one of our customers. While we succeeded in creating a full-fledged mobile app that scored great reviews with our customer’s user base, the road that took us there was much more stony than we expected, and we often found ourselves hitting walls where we did expect smooth sailing instead. In this blogpost, I want to share ten tips to ease the pain and provide a smooth development experience with Apache Cordova.
1. Use a task runner on top of Cordova
You can greatly streamline and simplify your workflow if you use a task runner like Grunt or Gulp on top of Cordova to orchestrate your build tasks. Grunt is what we use, and we utilize the grunt-cordovacli plugin in order to steer cordova. This way, we never have to take care of building and configuring our code before running the app; instead we do a simple „grunt run:android“ in order to consistently build and run our application on the Android emulator.
2. Scaffold Cordova in your build process
For us, maintaining the Cordova project directory within our git repository was a constant pain. It is not always clear which files are generated and which need to be checked in and, even worse, this has a tendency to change between CLI and platform versions. After updating plugins, we would sometimes run into obscure build errors that required removing and re-adding a platform. In addition, we have lokal forks of a couple of plugins in our codebase that needed to be kept in sync with the installed versions in the project directory.
After some time, we got tired of working with this rather brittle setup and resolved to remove the project directory from our repository alltogether. Instead, we have automatized the scaffolding process using grunt and grunt-cordovacli by calling Cordova from our Gruntfile. The configuration and build hooks (see below) are copied into the project folder after scaffolding, and the list of plugins and platforms is encoded in our Gruntfile. This turned out to be a huge improvement for us:
- All settings are immediatelly transparent from looking at the config file and at the Gruntfile
- We always build from a consisten Cordova setup
- Updating plugin and platform versions is a breeze: just update the Gruntfile and do a full rebuild
We can only recommend this mode of operation: it fully removes the pain of managing the project directory.
3. Use hooks to perform any modifications to the generated project files
Face it: while you do not want to touch the generated files, there comes the day where you have to make a modification to the Xcode plist file. And then a gradle parameter. And then another one. And suddenly, you find yourself in the hell that is modifying autogenerated files. However, there is a remedy for the pain: Cordova build hooks.
4. Use native remote debugging or weinre
This will be old news to people with mobile web development experience, but there we go nevertheless: you can remote debug the webview in Chrome and in Safari. For both Android and iOS, remote debugging works just as with any ordinary web page — you have full access to the developer tools, both on the emulator and on real devices connected via USB.
On iOS, remote debugging is only available if you run the app directly from Xcode. If you package the app for distribution, the feature will be deactivated. On Android, the target device needs to run at least Android 4.4. If you do a release build, Cordova will disable remote debugging on Android, too.
5. Get familiar with the native tools
Even though Cordova tries to abstract the particularities of the different platforms for you, there will come a point where the abstraction breaks down and you will have to face the native development tools in single-hand combat. Even if you do not encounter any problems that involve native code, the list of contact points is still long: installing the necessary SDK components, connecting to devices, viewing device logs and codesigning for release all involve some degree of interaction with the native SDK. Finally, if you have to rely on third-party plugins, it may well happen that you will encounter roadblocks that will involve debugging and possibly fixing native code.
The upshot: get to know the native Android and iOS tools. If you know your way around these and also sport some Java and Objective-C skills (or at least have access to someone who does), you will have much smoother sailing. Cordova projects can be easily imported in both Xcode and Android studio, and debugging the native code works as expected.
6. Test on as many devices as possible, use emulators
Ever heard of device fragmentation? After developing an Android application with Cordova, you will know what it is. Every Android version sports its own webview implementation, vendors apply their own fixes, and you end up with pandora’s box. To be fair, it should be mentioned that things have gotten much better with Android 4.4: starting with 4.4, the webview is based on chrome, and starting with 5.0, it is regularly updated via the playstore. Still, if you don’t want to leave about (currently) 25% of potential customers in the cold, you have to support what is basically a pandaemonium of broken and buggy webkit browsers.
If you don’t want to swamped in minor and major glitches and bugs just before release, it is vital that you test your app on as many devices and as early as possible. Emulators are a great way to cover all relevant OS versions, but you should still try to get your hands on a couple of real devices. For us, our Open Device Lab provided an invaluable pool of test devices.
With iOS, the situation is much better, but you still should test your app on different devices in order to get an idea of how it will look like. If you don’t discover possible issues yourself, Apple will do so during review and potentially reject your app.
7. Use Crosswalk for Android
If you don’t have to support Android older than 4.0, Crosswalk is an awesome way to get rid of all problems related to webview fragmentation on Android. Crosswalk is portable webview based on chrome mobile, and installing the corresponding plugin will replace the system webview in your app. This way, you will great HTML5 support, remote debugging and, most importantly, a consistent and dependable runtime environment on all Android versions.
Moreover, Crosswalk will protect you from unforseen changes introduced by automatically deployed updates to the system webview on Android 5.0 and higher. On one occassion, parts of our app stopped working after such an automatic update, and an update on our end was required in order to get things running again. Had we already been using Crosswalk back then, the change would have been under our control and this would not have happened.
The price you pay for Crosswalk is an increase in size of the resulting app package of about 25MB. Moreover, Crosswalk is a binary component, and you will have to publish separate packages for ARM and x86 into the Playstore. Still, we think the enormous gain of a normalized target platform is worth the resulting complications in the deployment process.
8. Be wary of buggy plugins
After struggling with broken third-party code more than one time to often, we are convinced that reviewing plugins carefully before including them will save you a lot of nerves, time and, subsequently, money. Check if the code looks reasonable, whether the issue tracker is flowing over and whether pull requests are reviewed and merged in a timely manner. If a plugin looks fishy, try to find an alternative instead. If you can’t, test it thoroughly before including and be prepared to debug and modify it if necessary.
For us, including the more problematic plugins into our repository via git-subtree worked well. This way, we can reference the local copies when installing them into cordova, and we can track our modification in our git repository. As cordova supports installing plugins directly from a git repository, forking plugins on github is a viable alternative, too — especially if you want to be a good citizen and contribute your changes back.
9. Don’t be afraid to create your own plugins
Talking about plugins: if you know a bit of Java and Objective-C, creating them is pretty simple, and you should not be afraid to create your own plugins as necessary. We currently use several plugins that we created ourselves when we couldn’t find any exisiting solutions. Two of them — cordova-android-scrollbar and cordova-android-movetasktoback — are open source, and we hope to release the others once we find time to polish it for general use.
The point here is that, while we started out with the goal of developing our app without touching any native code, this approach just wouldn’t work out. Using the plugin mechanism you can use native code where necessary while keeping the bulk of your application portable and cross-platform. Sure, you will end up with a small non-portable part of your application that has to be maintained for each platform separately, but the reward is full access to the native APIs where you need it.
10. Familarize yourself with the deployment process
Before you can submit to Appstore and Playstore, your app will have to meet various requirements, and you will have to supply a set of assets that will be used to showcase app for potential customers in the stores. Your app will have to be properly codesigned and, in case of iOS, will have to pass through Apple’s review process. In addition, before publishing, you will have to get your application installed on the devices of test users. Familiarizing yourself with the publishing and deployment process early during development will give you enough time to collect all required assets, develop a strategy for beta testing and will save you time and headaches later on.