When a Hybrid app gets to a certan complexity, you get to the point where you need a custom Cordova Plugin
After 9 months of running a production Ionic App (HungerPerks), we finally got to the point where we needed a custom Cordova plugin, distinct enough to not be able to just fork an existing one and make changes to it. Unfortunately, all the articles, Github repos, and documentation were all some combination of outdated, incomplete, or broken.
This article will broadly discuss:
- The parts of a Cordova plugin, and where they live in an Ionic app
- A simple example plugin
- How to develop a plugin in a sane way
Now let’s get started!!
The parts of a Cordova plugin
In an Ionic project (say ExampleProject), when you run
ionic cordova plugin add <some-cordova-plugin>
The Cordova cli goes to the repo where the plugin is stored, and pulls it into the plugins folder within the project (i.e. ExampleProject/plugins/some-cordova-plugin). This is essentially a storehouse for when ionic builds a platform. At this point, when you run
ionic cordova platform add <android/ios>
as a part of the platform add process, Ionic will copy the platform specefic plugin code into the platform build folder. This is where the plugin code lives that is actually deployed onto devices when built or run.
A simple example
Before continuing on, I would highly recommend reading this article on writing Cordova plugins, It discusses objective-c for the ios portion, but otherwise explains the parts of a Cordova plugin well.
Based off of that example, I have created a plugin that does most of the same things in swift 3. Take a look at https://github.com/mibzman/example-cordova-plugin. This plugin (as of Jan 12, ’18) works with the current version of ionic cli (3.19.0), as well as swift 3.2.
Now that we have these plugins, how do we actually use them in our ionic applications? For most developers, their only experience with plugins is through ionic-native, which provides nice typescript bindings. How do we actually call these custom plugins?
First look at the www/plugin.js of the plugin you want to integrate. The last line is:
module.exports = ExampleCordovaPlugin; You can take this info and use it in your ionic application like so:
Hooray! We used someone else’s plugin just like we’ve done all along! Now what?
How to develop a plugin
So how do we make changes? The first instinct I had was to make changes in the plugin repo in something like sublime, commit them, and reinstall the plugin in a test application. Spoiler alert: that’s terrible for many, many reasons. One big one is that it takes forever for changes regardless of size. How can we do it in a way that makes more sense?
iOS is a simple example. Open the
ExampleProject/platforms/ios/MyApp.xcodeproj file in Xcode, and take a peek in the plugins folder. In there you’ll find all the iOS project files from all the plugins, all unfolded. Somewhere in there is the file for the plugin you care about! Since we learned earlier that changes to the code in the platform folder can be deployed immediately, we can tweak and play away!
This same thing can be done with android studio with the platforms/android folder, but you should use the ionic-cli android build, the android studio build process seems to muck with the ionic gradle build stuff.
The only thing to keep in mind is that changes in these files have to be moved into your actual plugin repo. Since the platform folder is technically build output of ionic, the expectation is that it can be deleted whenever, so be sure to be proactive about moving your changes out of the platform folder.
Finally I noticed some wonkiness when changing plugin names or id’s, so as a rule of thumb if strange things are happening, take a peak at your project’s package.lock, remove references to your plugin, blow away that node_modules folder, and reinstall everything.
I’ve also published the example ionic application that works with this plugin at https://github.com/mibzman/PluginTester.